Skip to content

Commit

Permalink
Merge the develop branch to the master branch, preparation to v5.6.0-rc0
Browse files Browse the repository at this point in the history
  • Loading branch information
akolotov committed Dec 2, 2020
2 parents 835742d + 24e73c3 commit b858c96
Show file tree
Hide file tree
Showing 24 changed files with 204 additions and 81 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Expand Up @@ -80,9 +80,9 @@ jobs:
steps:
- uses: actions/checkout@v2
- if: startsWith(github.ref, 'refs/tags')
run: echo "::set-env name=DOCKER_TAGS::${GITHUB_REF#refs/tags/},latest"
run: echo "DOCKER_TAGS=${GITHUB_REF#refs/tags/},latest" >> $GITHUB_ENV
- if: startsWith(github.ref, 'refs/heads')
run: echo "::set-env name=DOCKER_TAGS::${GITHUB_REF#refs/heads/}-${GITHUB_SHA::8}"
run: echo "DOCKER_TAGS=${GITHUB_REF#refs/heads/}-${GITHUB_SHA::8}" >> $GITHUB_ENV
- uses: docker/build-push-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
Expand Down
4 changes: 2 additions & 2 deletions contracts/libraries/ArbitraryMessage.sol
Expand Up @@ -48,8 +48,8 @@ library ArbitraryMessage {
gasLimit := and(shr(64, blob), 0xffffffff)

dataType := byte(26, blob)
if gt(dataType, 0) {
// for now, only 0 datatype is supported - regular AMB calls
if gt(and(dataType, 0x7f), 0) {
// for now, only 0x00 and 0x80 datatypes are supported - regular AMB calls
// other dataType values are kept reserved for future use
revert(0, 0)
}
Expand Down
2 changes: 1 addition & 1 deletion contracts/mocks/AMBMock.sol
Expand Up @@ -46,7 +46,7 @@ contract AMBMock {
}

function requireToConfirmMessage(address _contract, bytes _data, uint256 _gas) external returns (bytes32) {
return _sendMessage(_contract, _data, _gas, 0xf0);
return _sendMessage(_contract, _data, _gas, 0x80);
}

function _sendMessage(address _contract, bytes _data, uint256 _gas, uint256 _dataType) internal returns (bytes32) {
Expand Down
22 changes: 14 additions & 8 deletions contracts/upgradeable_contracts/ReentrancyGuard.sol
@@ -1,15 +1,21 @@
pragma solidity 0.4.24;

import "../upgradeability/EternalStorage.sol";

contract ReentrancyGuard is EternalStorage {
bytes32 internal constant LOCK = 0x6168652c307c1e813ca11cfb3a601f1cf3b22452021a5052d8b05f1f1f8a3e92; // keccak256(abi.encodePacked("lock"))

function lock() internal returns (bool) {
return boolStorage[LOCK];
contract ReentrancyGuard {
function lock() internal returns (bool res) {
assembly {
// Even though this is not the same as boolStorage[keccak256(abi.encodePacked("lock"))],
// since solidity mapping introduces another level of addressing, such slot change is safe
// for temporary variables which are cleared at the end of the call execution.
res := sload(0x6168652c307c1e813ca11cfb3a601f1cf3b22452021a5052d8b05f1f1f8a3e92) // keccak256(abi.encodePacked("lock"))
}
}

function setLock(bool _lock) internal {
boolStorage[LOCK] = _lock;
assembly {
// Even though this is not the same as boolStorage[keccak256(abi.encodePacked("lock"))],
// since solidity mapping introduces another level of addressing, such slot change is safe
// for temporary variables which are cleared at the end of the call execution.
sstore(0x6168652c307c1e813ca11cfb3a601f1cf3b22452021a5052d8b05f1f1f8a3e92, _lock) // keccak256(abi.encodePacked("lock"))
}
}
}
3 changes: 3 additions & 0 deletions contracts/upgradeable_contracts/TokenBridgeMediator.sol
Expand Up @@ -10,6 +10,7 @@ import "./TransferInfoStorage.sol";
*/
contract TokenBridgeMediator is BasicAMBMediator, BasicTokenBridge, TransferInfoStorage {
event FailedMessageFixed(bytes32 indexed messageId, address recipient, uint256 value);
event TokensBridgingInitiated(address indexed sender, uint256 value, bytes32 indexed messageId);
event TokensBridged(address indexed recipient, uint256 value, bytes32 indexed messageId);

/**
Expand All @@ -32,6 +33,8 @@ contract TokenBridgeMediator is BasicAMBMediator, BasicTokenBridge, TransferInfo

setMessageValue(_messageId, _value);
setMessageRecipient(_messageId, _from);

emit TokensBridgingInitiated(_from, _value, _messageId);
}

/**
Expand Down
Expand Up @@ -50,7 +50,7 @@ contract BasicAMBErc20ToNative is Initializable, Upgradeable, Claimable, Version
* @return patch value of the version
*/
function getBridgeInterfacesVersion() external pure returns (uint64 major, uint64 minor, uint64 patch) {
return (1, 1, 1);
return (1, 2, 0);
}

/**
Expand Down
Expand Up @@ -96,7 +96,7 @@ contract BasicAMBErc677ToErc677 is
}

function getBridgeInterfacesVersion() external pure returns (uint64 major, uint64 minor, uint64 patch) {
return (1, 3, 0);
return (1, 4, 0);
}

function getBridgeMode() external pure returns (bytes4 _data) {
Expand Down
Expand Up @@ -4,7 +4,7 @@ import "./BasicAMBErc677ToErc677.sol";

contract BasicStakeTokenMediator is BasicAMBErc677ToErc677 {
function getBridgeInterfacesVersion() external pure returns (uint64 major, uint64 minor, uint64 patch) {
return (1, 2, 0);
return (1, 3, 0);
}

function getBridgeMode() external pure returns (bytes4 _data) {
Expand Down
Expand Up @@ -61,7 +61,7 @@ contract BasicAMBNativeToErc20 is
* @return patch value of the version
*/
function getBridgeInterfacesVersion() external pure returns (uint64 major, uint64 minor, uint64 patch) {
return (1, 1, 0);
return (1, 2, 0);
}

/**
Expand Down
Expand Up @@ -15,7 +15,7 @@ contract BasicHomeAMB is BasicAMB, MessageDelivery {
uint256 NumberOfCollectedSignatures
);

uint256 internal constant SEND_TO_MANUAL_LANE = 0xf0;
uint256 internal constant SEND_TO_MANUAL_LANE = 0x80;

function executeAffirmation(bytes message) external onlyValidator {
bytes32 hashMsg = keccak256(abi.encodePacked(message));
Expand Down
Expand Up @@ -4,10 +4,6 @@ import "../../upgradeability/EternalStorage.sol";
import "../../libraries/Bytes.sol";

contract MessageProcessor is EternalStorage {
bytes32 internal constant MESSAGE_SENDER = 0x7b58b2a669d8e0992eae9eaef641092c0f686fd31070e7236865557fa1571b5b; // keccak256(abi.encodePacked("messageSender"))
bytes32 internal constant MESSAGE_ID = 0xe34bb2103dc34f2c144cc216c132d6ffb55dac57575c22e089161bbe65083304; // keccak256(abi.encodePacked("messageId"))
bytes32 internal constant MESSAGE_SOURCE_CHAIN_ID = 0x7f0fcd9e49860f055dd0c1682d635d309ecb5e3011654c716d9eb59a7ddec7d2; // keccak256(abi.encodePacked("messageSourceChainId"))

/**
* @dev Returns a status of the message that came from the other side.
* @param _messageId id of the message from the other side that triggered a call.
Expand Down Expand Up @@ -89,24 +85,39 @@ contract MessageProcessor is EternalStorage {
* Can be used by executors for getting other side caller address.
* @return address of the sender on the other side.
*/
function messageSender() external view returns (address) {
return addressStorage[MESSAGE_SENDER];
function messageSender() external view returns (address sender) {
assembly {
// Even though this is not the same as addressStorage[keccak256(abi.encodePacked("messageSender"))],
// since solidity mapping introduces another level of addressing, such slot change is safe
// for temporary variables which are cleared at the end of the call execution.
sender := sload(0x7b58b2a669d8e0992eae9eaef641092c0f686fd31070e7236865557fa1571b5b) // keccak256(abi.encodePacked("messageSender"))
}
}

/**
* @dev Sets an address of the sender on the other side for the currently processed message.
* @param _sender address of the sender on the other side.
*/
function setMessageSender(address _sender) internal {
addressStorage[MESSAGE_SENDER] = _sender;
assembly {
// Even though this is not the same as addressStorage[keccak256(abi.encodePacked("messageSender"))],
// since solidity mapping introduces another level of addressing, such slot change is safe
// for temporary variables which are cleared at the end of the call execution.
sstore(0x7b58b2a669d8e0992eae9eaef641092c0f686fd31070e7236865557fa1571b5b, _sender) // keccak256(abi.encodePacked("messageSender"))
}
}

/**
* @dev Returns an id of the currently processed message.
* @return id of the message that originated on the other side.
*/
function messageId() public view returns (bytes32) {
return bytes32(uintStorage[MESSAGE_ID]);
function messageId() public view returns (bytes32 id) {
assembly {
// Even though this is not the same as uintStorage[keccak256(abi.encodePacked("messageId"))],
// since solidity mapping introduces another level of addressing, such slot change is safe
// for temporary variables which are cleared at the end of the call execution.
id := sload(0xe34bb2103dc34f2c144cc216c132d6ffb55dac57575c22e089161bbe65083304) // keccak256(abi.encodePacked("messageId"))
}
}

/**
Expand All @@ -124,23 +135,38 @@ contract MessageProcessor is EternalStorage {
* @param _messageId id of the message that originated on the other side.
*/
function setMessageId(bytes32 _messageId) internal {
uintStorage[MESSAGE_ID] = uint256(_messageId);
assembly {
// Even though this is not the same as uintStorage[keccak256(abi.encodePacked("messageId"))],
// since solidity mapping introduces another level of addressing, such slot change is safe
// for temporary variables which are cleared at the end of the call execution.
sstore(0xe34bb2103dc34f2c144cc216c132d6ffb55dac57575c22e089161bbe65083304, _messageId) // keccak256(abi.encodePacked("messageId"))
}
}

/**
* @dev Returns an originating chain id of the currently processed message.
* @return source chain id of the message that originated on the other side.
*/
function messageSourceChainId() external view returns (uint256) {
return uintStorage[MESSAGE_SOURCE_CHAIN_ID];
function messageSourceChainId() external view returns (uint256 id) {
assembly {
// Even though this is not the same as uintStorage[keccak256(abi.encodePacked("messageSourceChainId"))],
// since solidity mapping introduces another level of addressing, such slot change is safe
// for temporary variables which are cleared at the end of the call execution.
id := sload(0x7f0fcd9e49860f055dd0c1682d635d309ecb5e3011654c716d9eb59a7ddec7d2) // keccak256(abi.encodePacked("messageSourceChainId"))
}
}

/**
* @dev Returns an originating chain id of the currently processed message.
* @return source chain id of the message that originated on the other side.
* @dev Sets an originating chain id of the currently processed message.
* @param _sourceChainId source chain id of the message that originated on the other side.
*/
function setMessageSourceChainId(uint256 _sourceChainId) internal returns (uint256) {
uintStorage[MESSAGE_SOURCE_CHAIN_ID] = _sourceChainId;
function setMessageSourceChainId(uint256 _sourceChainId) internal {
assembly {
// Even though this is not the same as uintStorage[keccak256(abi.encodePacked("messageSourceChainId"))],
// since solidity mapping introduces another level of addressing, such slot change is safe
// for temporary variables which are cleared at the end of the call execution.
sstore(0x7f0fcd9e49860f055dd0c1682d635d309ecb5e3011654c716d9eb59a7ddec7d2, _sourceChainId) // keccak256(abi.encodePacked("messageSourceChainId"))
}
}

/**
Expand Down Expand Up @@ -195,15 +221,15 @@ contract MessageProcessor is EternalStorage {
setMessageSourceChainId(_sourceChainId);

// After EIP-150, max gas cost allowed to be passed to the internal call is equal to the 63/64 of total gas left.
// In reallity, min(gasLimit, 63/64 * gasleft()) will be used as the call gas limit.
// In reality, min(gasLimit, 63/64 * gasleft()) will be used as the call gas limit.
// Imagine a situation, when message requires 10000000 gas to be executed successfully.
// Also suppose, that at this point, gasleft() is equal to 10158000, so the callee will receive ~ 10158000 * 63 / 64 = 9999300 gas.
// That amount of gas is not enough, so the call will fail. At the same time,
// even if the callee failed the bridge contract still has ~ 158000 gas to
// finish its execution and it will be enough. The internal call fails but
// only because the oracle provides incorrect gas limit for the transaction
// This check is needed here in order to force contract to pass exactly the requested amount of gas.
// Avoiding it may leed to the unwanted message failure in some extreme cases.
// Avoiding it may lead to the unwanted message failure in some extreme cases.
require((gasleft() * 63) / 64 > _gas);

bool status = _contract.call.gas(_gas)(_data);
Expand Down
Expand Up @@ -17,6 +17,6 @@ contract VersionableAMB is VersionableBridge {
* @return (major, minor, patch) version triple
*/
function getBridgeInterfacesVersion() external pure returns (uint64 major, uint64 minor, uint64 patch) {
return (5, 4, 0);
return (5, 5, 0);
}
}
Expand Up @@ -58,7 +58,7 @@ contract BasicMultiAMBErc20ToErc677 is
* @return patch value of the version
*/
function getBridgeInterfacesVersion() external pure returns (uint64 major, uint64 minor, uint64 patch) {
return (1, 2, 0);
return (1, 3, 0);
}

/**
Expand Down Expand Up @@ -88,5 +88,6 @@ contract BasicMultiAMBErc20ToErc677 is
function _relayTokens(ERC677 token, address _receiver, uint256 _value) internal;

/* solcov ignore next */
function bridgeSpecificActionsOnTokenTransfer(ERC677 _token, address _from, uint256 _value, bytes _data) internal;
function bridgeSpecificActionsOnTokenTransfer(ERC677 _token, address _from, address _receiver, uint256 _value)
internal;
}
Expand Up @@ -70,7 +70,7 @@ contract ForeignMultiAMBErc20ToErc677 is BasicMultiAMBErc20ToErc677 {
function onTokenTransfer(address _from, uint256 _value, bytes _data) public returns (bool) {
if (!lock()) {
ERC677 token = ERC677(msg.sender);
bridgeSpecificActionsOnTokenTransfer(token, _from, _value, _data);
bridgeSpecificActionsOnTokenTransfer(token, _from, chooseReceiver(_from, _data), _value);
}
return true;
}
Expand Down Expand Up @@ -104,19 +104,19 @@ contract ForeignMultiAMBErc20ToErc677 is BasicMultiAMBErc20ToErc677 {
setLock(true);
token.safeTransferFrom(msg.sender, _value);
setLock(false);
bridgeSpecificActionsOnTokenTransfer(token, msg.sender, _value, abi.encodePacked(_receiver));
bridgeSpecificActionsOnTokenTransfer(token, msg.sender, _receiver, _value);
}

/**
* @dev Executes action on deposit of bridged tokens
* @param _token address of the token contract
* @param _from address of tokens sender
* @param _value requsted amount of bridged tokens
* @param _data alternative receiver, if specified
* @param _receiver address of tokens receiver on the other side
* @param _value requested amount of bridged tokens
*/
function bridgeSpecificActionsOnTokenTransfer(ERC677 _token, address _from, uint256 _value, bytes _data) internal {
if (lock()) return;

function bridgeSpecificActionsOnTokenTransfer(ERC677 _token, address _from, address _receiver, uint256 _value)
internal
{
bool isKnownToken = isTokenRegistered(_token);
if (!isKnownToken) {
string memory name = TokenReader.readName(_token);
Expand All @@ -132,18 +132,17 @@ contract ForeignMultiAMBErc20ToErc677 is BasicMultiAMBErc20ToErc677 {
addTotalSpentPerDay(_token, getCurrentDay(), _value);

bytes memory data;
address receiver = chooseReceiver(_from, _data);

if (isKnownToken) {
data = abi.encodeWithSelector(this.handleBridgedTokens.selector, _token, receiver, _value);
data = abi.encodeWithSelector(this.handleBridgedTokens.selector, _token, _receiver, _value);
} else {
data = abi.encodeWithSelector(
HomeMultiAMBErc20ToErc677(this).deployAndHandleBridgedTokens.selector,
_token,
name,
symbol,
decimals,
receiver,
_receiver,
_value
);
}
Expand All @@ -163,6 +162,8 @@ contract ForeignMultiAMBErc20ToErc677 is BasicMultiAMBErc20ToErc677 {
if (!isKnownToken) {
_setTokenRegistrationMessageId(_token, _messageId);
}

emit TokensBridgingInitiated(_token, _from, _value, _messageId);
}

/**
Expand Down

0 comments on commit b858c96

Please sign in to comment.