Skip to content

Commit 835742d

Browse files
authored
Merge the develop branch to the master branch, preparation to v5.5.0
2 parents b22383f + d8a9f8c commit 835742d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+990
-298
lines changed

contracts/ERC677BridgeToken.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ contract ERC677BridgeToken is IBurnableMintableERC677Token, DetailedERC20, Burna
4646
}
4747

4848
function getTokenInterfacesVersion() external pure returns (uint64 major, uint64 minor, uint64 patch) {
49-
return (2, 2, 0);
49+
return (2, 4, 0);
5050
}
5151

5252
function superTransfer(address _to, uint256 _value) internal returns (bool) {

contracts/PermittableToken.sol

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -163,9 +163,4 @@ contract PermittableToken is ERC677BridgeToken {
163163
function _now() internal view returns (uint256) {
164164
return now;
165165
}
166-
167-
/// @dev Version of the token contract.
168-
function getTokenInterfacesVersion() external pure returns (uint64 major, uint64 minor, uint64 patch) {
169-
return (2, 3, 0);
170-
}
171166
}

contracts/interfaces/IAMB.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ interface IAMB {
1111
function failedMessageReceiver(bytes32 _messageId) external view returns (address);
1212
function failedMessageSender(bytes32 _messageId) external view returns (address);
1313
function requireToPassMessage(address _contract, bytes _data, uint256 _gas) external returns (bytes32);
14+
function requireToConfirmMessage(address _contract, bytes _data, uint256 _gas) external returns (bytes32);
1415
function sourceChainId() external view returns (uint256);
1516
function destinationChainId() external view returns (uint256);
1617
}

contracts/mocks/AMBMock.sol

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,14 @@ contract AMBMock {
4242
}
4343

4444
function requireToPassMessage(address _contract, bytes _data, uint256 _gas) external returns (bytes32) {
45+
return _sendMessage(_contract, _data, _gas, 0x00);
46+
}
47+
48+
function requireToConfirmMessage(address _contract, bytes _data, uint256 _gas) external returns (bytes32) {
49+
return _sendMessage(_contract, _data, _gas, 0xf0);
50+
}
51+
52+
function _sendMessage(address _contract, bytes _data, uint256 _gas, uint256 _dataType) internal returns (bytes32) {
4553
require(messageId == bytes32(0));
4654
bytes32 bridgeId = keccak256(abi.encodePacked(uint16(1337), address(this))) &
4755
0x00000000ffffffffffffffffffffffffffffffffffffffff0000000000000000;
@@ -55,7 +63,7 @@ contract AMBMock {
5563
uint32(_gas),
5664
uint8(2),
5765
uint8(2),
58-
uint8(0x00),
66+
uint8(_dataType),
5967
uint16(1337),
6068
uint16(1338),
6169
_data

contracts/mocks/Box.sol

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,10 @@ contract Box {
4545
bytes memory encodedData = abi.encodeWithSelector(methodSelector, _i);
4646
IAMB(_bridge).requireToPassMessage(_executor, encodedData, 141647);
4747
}
48+
49+
function setValueOnOtherNetworkUsingManualLane(uint256 _i, address _bridge, address _executor) public {
50+
bytes4 methodSelector = this.setValue.selector;
51+
bytes memory encodedData = abi.encodeWithSelector(methodSelector, _i);
52+
IAMB(_bridge).requireToConfirmMessage(_executor, encodedData, 141647);
53+
}
4854
}

contracts/upgradeable_contracts/BaseFeeManager.sol

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ contract BaseFeeManager is EternalStorage, FeeTypes {
1616
bytes32 internal constant HOME_FEE_STORAGE_KEY = 0xc3781f3cec62d28f56efe98358f59c2105504b194242dbcb2cc0806850c306e7; // keccak256(abi.encodePacked("homeFee"))
1717
bytes32 internal constant FOREIGN_FEE_STORAGE_KEY = 0x68c305f6c823f4d2fa4140f9cf28d32a1faccf9b8081ff1c2de11cf32c733efc; // keccak256(abi.encodePacked("foreignFee"))
1818

19+
/**
20+
* @dev Calculated the amount of fee for the particular bridge operation.
21+
* @param _value bridged amount of tokens/coins for which fee amount is calculated.
22+
* @param _recover true, if the fee was already subtracted from the given _value and needs to be restored.
23+
* @param _feeType type of the fee, should be either HOME_FEE of FOREIGN_FEE.
24+
* @return calculated fee amount.
25+
*/
1926
function calculateFee(uint256 _value, bool _recover, bytes32 _feeType)
2027
public
2128
view

contracts/upgradeable_contracts/BaseOverdrawManagement.sol

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,42 +2,63 @@ pragma solidity 0.4.24;
22

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

5+
/**
6+
* @title BaseOverdrawManagement
7+
* @dev This contract implements basic functionality for tracking execution bridge operations that are out of limits.
8+
*/
59
contract BaseOverdrawManagement is EternalStorage {
6-
event AmountLimitExceeded(address recipient, uint256 value, bytes32 transactionHash);
7-
event AssetAboveLimitsFixed(bytes32 indexed transactionHash, uint256 value, uint256 remaining);
10+
event MediatorAmountLimitExceeded(address recipient, uint256 value, bytes32 indexed messageId);
11+
event AmountLimitExceeded(address recipient, uint256 value, bytes32 indexed transactionHash, bytes32 messageId);
12+
event AssetAboveLimitsFixed(bytes32 indexed messageId, uint256 value, uint256 remaining);
813

914
bytes32 internal constant OUT_OF_LIMIT_AMOUNT = 0x145286dc85799b6fb9fe322391ba2d95683077b2adf34dd576dedc437e537ba7; // keccak256(abi.encodePacked("outOfLimitAmount"))
1015

16+
/**
17+
* @dev Total amount coins/tokens that were bridged from the other side and are out of execution limits.
18+
* @return total amount of all bridge operations above limits.
19+
*/
1120
function outOfLimitAmount() public view returns (uint256) {
1221
return uintStorage[OUT_OF_LIMIT_AMOUNT];
1322
}
1423

15-
function fixedAssets(bytes32 _txHash) public view returns (bool) {
16-
return boolStorage[keccak256(abi.encodePacked("fixedAssets", _txHash))];
17-
}
18-
24+
/**
25+
* @dev Internal function for updating a total amount that is out of execution limits.
26+
* @param _value new value for the total amount of bridge operations above limits.
27+
*/
1928
function setOutOfLimitAmount(uint256 _value) internal {
2029
uintStorage[OUT_OF_LIMIT_AMOUNT] = _value;
2130
}
2231

23-
function txAboveLimits(bytes32 _txHash) internal view returns (address recipient, uint256 value) {
24-
recipient = addressStorage[keccak256(abi.encodePacked("txOutOfLimitRecipient", _txHash))];
25-
value = uintStorage[keccak256(abi.encodePacked("txOutOfLimitValue", _txHash))];
26-
}
27-
28-
function setTxAboveLimits(address _recipient, uint256 _value, bytes32 _txHash) internal {
29-
addressStorage[keccak256(abi.encodePacked("txOutOfLimitRecipient", _txHash))] = _recipient;
30-
setTxAboveLimitsValue(_value, _txHash);
32+
/**
33+
* @dev Internal function for retrieving information about out-of-limits bridge operation.
34+
* @param _messageId id of the message that cause above-limits error.
35+
* @return (address of the receiver, amount of coins/tokens in the bridge operation)
36+
*/
37+
function txAboveLimits(bytes32 _messageId) internal view returns (address recipient, uint256 value) {
38+
recipient = addressStorage[keccak256(abi.encodePacked("txOutOfLimitRecipient", _messageId))];
39+
value = uintStorage[keccak256(abi.encodePacked("txOutOfLimitValue", _messageId))];
3140
}
3241

33-
function setTxAboveLimitsValue(uint256 _value, bytes32 _txHash) internal {
34-
uintStorage[keccak256(abi.encodePacked("txOutOfLimitValue", _txHash))] = _value;
42+
/**
43+
* @dev Internal function for updating information about tbe out-of-limits bridge operation.
44+
* @param _recipient receiver specified in the bridge operation.
45+
* @param _value amount of coins/tokens inside the bridge operation.
46+
* @param _messageId id of the message that cause above-limits error.
47+
*/
48+
function setTxAboveLimits(address _recipient, uint256 _value, bytes32 _messageId) internal {
49+
addressStorage[keccak256(abi.encodePacked("txOutOfLimitRecipient", _messageId))] = _recipient;
50+
setTxAboveLimitsValue(_value, _messageId);
3551
}
3652

37-
function setFixedAssets(bytes32 _txHash) internal {
38-
boolStorage[keccak256(abi.encodePacked("fixedAssets", _txHash))] = true;
53+
/**
54+
* @dev Internal function for updating information about the remaining value of out-of-limits bridge operation.
55+
* @param _value amount of coins/tokens inside the bridge operation.
56+
* @param _messageId id of the message that cause above-limits error.
57+
*/
58+
function setTxAboveLimitsValue(uint256 _value, bytes32 _messageId) internal {
59+
uintStorage[keccak256(abi.encodePacked("txOutOfLimitValue", _messageId))] = _value;
3960
}
4061

4162
/* solcov ignore next */
42-
function fixAssetsAboveLimits(bytes32 txHash, bool unlockOnForeign, uint256 valueToUnlock) external;
63+
function fixAssetsAboveLimits(bytes32 messageId, bool unlockOnForeign, uint256 valueToUnlock) external;
4364
}

contracts/upgradeable_contracts/BasicHomeBridge.sol

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ import "../libraries/Message.sol";
88
import "./BasicBridge.sol";
99
import "./BasicTokenBridge.sol";
1010

11+
/**
12+
* @title BasicHomeBridge
13+
* @dev This contract implements common functionality for all vanilla bridge modes on the Home side.
14+
*/
1115
contract BasicHomeBridge is EternalStorage, Validatable, BasicBridge, BasicTokenBridge {
1216
using SafeMath for uint256;
1317

@@ -21,9 +25,16 @@ contract BasicHomeBridge is EternalStorage, Validatable, BasicBridge, BasicToken
2125
uint256 NumberOfCollectedSignatures
2226
);
2327

28+
/**
29+
* @dev Executes a message affirmation for some Foreign side event.
30+
* Can be called only by a current bridge validator.
31+
* @param recipient tokens/coins of receiver address, where the assets should be unlocked/minted.
32+
* @param value amount of assets to unlock/mint.
33+
* @param transactionHash reference event transaction hash on the Foreign side of the bridge.
34+
*/
2435
function executeAffirmation(address recipient, uint256 value, bytes32 transactionHash) external onlyValidator {
36+
bytes32 hashMsg = keccak256(abi.encodePacked(recipient, value, transactionHash));
2537
if (withinExecutionLimit(value)) {
26-
bytes32 hashMsg = keccak256(abi.encodePacked(recipient, value, transactionHash));
2738
bytes32 hashSender = keccak256(abi.encodePacked(msg.sender, hashMsg));
2839
// Duplicated affirmations
2940
require(!affirmationsSigned(hashSender));
@@ -43,12 +54,12 @@ contract BasicHomeBridge is EternalStorage, Validatable, BasicBridge, BasicToken
4354
// it will couse funds lock on the home side of the bridge
4455
setNumAffirmationsSigned(hashMsg, markAsProcessed(signed));
4556
if (value > 0) {
46-
require(onExecuteAffirmation(recipient, value, transactionHash));
57+
require(onExecuteAffirmation(recipient, value, transactionHash, hashMsg));
4758
}
4859
emit AffirmationCompleted(recipient, value, transactionHash);
4960
}
5061
} else {
51-
onFailedAffirmation(recipient, value, transactionHash);
62+
onFailedAffirmation(recipient, value, transactionHash, hashMsg);
5263
}
5364
}
5465

@@ -92,7 +103,10 @@ contract BasicHomeBridge is EternalStorage, Validatable, BasicBridge, BasicToken
92103
}
93104

94105
/* solcov ignore next */
95-
function onExecuteAffirmation(address, uint256, bytes32) internal returns (bool);
106+
function onExecuteAffirmation(address, uint256, bytes32, bytes32) internal returns (bool);
107+
108+
/* solcov ignore next */
109+
function onFailedAffirmation(address, uint256, bytes32, bytes32) internal;
96110

97111
/* solcov ignore next */
98112
function onSignaturesCollected(bytes) internal;
@@ -153,7 +167,4 @@ contract BasicHomeBridge is EternalStorage, Validatable, BasicBridge, BasicToken
153167
function requiredMessageLength() public pure returns (uint256) {
154168
return Message.requiredMessageLength();
155169
}
156-
157-
/* solcov ignore next */
158-
function onFailedAffirmation(address, uint256, bytes32) internal;
159170
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
pragma solidity 0.4.24;
2+
3+
import "openzeppelin-solidity/contracts/math/SafeMath.sol";
4+
import "./Upgradeable.sol";
5+
import "./RewardableBridge.sol";
6+
import "./BasicHomeBridge.sol";
7+
import "./BaseOverdrawManagement.sol";
8+
9+
/**
10+
* @title HomeOverdrawManagement
11+
* @dev This contract implements functionality for recovering from out-of-limits executions in Home side vanilla bridges.
12+
*/
13+
contract HomeOverdrawManagement is BaseOverdrawManagement, RewardableBridge, Upgradeable, BasicHomeBridge {
14+
using SafeMath for uint256;
15+
16+
/**
17+
* @dev Fixes locked tokens, that were out of execution limits during the call to executeAffirmation.
18+
* @param hashMsg reference for bridge operation that was out of execution limits.
19+
* @param unlockOnForeign true if fixed tokens should be unlocked to the other side of the bridge.
20+
* @param valueToUnlock unlocked amount of tokens, should be less than txAboveLimitsValue.
21+
* Should be less than maxPerTx(), if tokens need to be unlocked on the other side.
22+
*/
23+
function fixAssetsAboveLimits(bytes32 hashMsg, bool unlockOnForeign, uint256 valueToUnlock)
24+
external
25+
onlyIfUpgradeabilityOwner
26+
{
27+
uint256 signed = numAffirmationsSigned(hashMsg);
28+
require(!isAlreadyProcessed(signed));
29+
(address recipient, uint256 value) = txAboveLimits(hashMsg);
30+
require(recipient != address(0) && value > 0 && value >= valueToUnlock);
31+
setOutOfLimitAmount(outOfLimitAmount().sub(valueToUnlock));
32+
uint256 pendingValue = value.sub(valueToUnlock);
33+
setTxAboveLimitsValue(pendingValue, hashMsg);
34+
emit AssetAboveLimitsFixed(hashMsg, valueToUnlock, pendingValue);
35+
if (unlockOnForeign) {
36+
require(valueToUnlock <= maxPerTx());
37+
address feeManager = feeManagerContract();
38+
uint256 eventValue = valueToUnlock;
39+
if (feeManager != address(0)) {
40+
uint256 fee = calculateFee(valueToUnlock, false, feeManager, HOME_FEE);
41+
eventValue = valueToUnlock.sub(fee);
42+
}
43+
emit UserRequestForSignature(recipient, eventValue);
44+
}
45+
}
46+
47+
/**
48+
* @dev Internal function for clearing above limits markers for some failed transfer.
49+
* Useful when transfer is being reprocessed on a new day or after limits were updated.
50+
* It is required that fixAssetsAboveLimits was not called on the failed transfer before prior to this function.
51+
* @param _hashMsg hash of the message, works as a unique indentifier.
52+
* @param _value transferred amount of tokens/coins in the fixed message.
53+
*/
54+
function _clearAboveLimitsMarker(bytes32 _hashMsg, uint256 _value) internal {
55+
(address aboveLimitsRecipient, uint256 aboveLimitsValue) = txAboveLimits(_hashMsg);
56+
// check if transfer was marked as out of limits
57+
if (aboveLimitsRecipient != address(0)) {
58+
// revert if a given transaction hash was already processed by the call to fixAssetsAboveLimits
59+
require(aboveLimitsValue == _value);
60+
setTxAboveLimits(address(0), 0, _hashMsg);
61+
setOutOfLimitAmount(outOfLimitAmount().sub(_value));
62+
}
63+
}
64+
}

contracts/upgradeable_contracts/OverdrawManagement.sol

Lines changed: 0 additions & 41 deletions
This file was deleted.

0 commit comments

Comments
 (0)