Skip to content

Commit

Permalink
Merge the develop branch to the master branch, preparation to v5.5.0
Browse files Browse the repository at this point in the history
  • Loading branch information
akolotov committed Nov 7, 2020
2 parents b22383f + d8a9f8c commit 835742d
Show file tree
Hide file tree
Showing 41 changed files with 990 additions and 298 deletions.
2 changes: 1 addition & 1 deletion contracts/ERC677BridgeToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ contract ERC677BridgeToken is IBurnableMintableERC677Token, DetailedERC20, Burna
}

function getTokenInterfacesVersion() external pure returns (uint64 major, uint64 minor, uint64 patch) {
return (2, 2, 0);
return (2, 4, 0);
}

function superTransfer(address _to, uint256 _value) internal returns (bool) {
Expand Down
5 changes: 0 additions & 5 deletions contracts/PermittableToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,4 @@ contract PermittableToken is ERC677BridgeToken {
function _now() internal view returns (uint256) {
return now;
}

/// @dev Version of the token contract.
function getTokenInterfacesVersion() external pure returns (uint64 major, uint64 minor, uint64 patch) {
return (2, 3, 0);
}
}
1 change: 1 addition & 0 deletions contracts/interfaces/IAMB.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ interface IAMB {
function failedMessageReceiver(bytes32 _messageId) external view returns (address);
function failedMessageSender(bytes32 _messageId) external view returns (address);
function requireToPassMessage(address _contract, bytes _data, uint256 _gas) external returns (bytes32);
function requireToConfirmMessage(address _contract, bytes _data, uint256 _gas) external returns (bytes32);
function sourceChainId() external view returns (uint256);
function destinationChainId() external view returns (uint256);
}
10 changes: 9 additions & 1 deletion contracts/mocks/AMBMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ contract AMBMock {
}

function requireToPassMessage(address _contract, bytes _data, uint256 _gas) external returns (bytes32) {
return _sendMessage(_contract, _data, _gas, 0x00);
}

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

function _sendMessage(address _contract, bytes _data, uint256 _gas, uint256 _dataType) internal returns (bytes32) {
require(messageId == bytes32(0));
bytes32 bridgeId = keccak256(abi.encodePacked(uint16(1337), address(this))) &
0x00000000ffffffffffffffffffffffffffffffffffffffff0000000000000000;
Expand All @@ -55,7 +63,7 @@ contract AMBMock {
uint32(_gas),
uint8(2),
uint8(2),
uint8(0x00),
uint8(_dataType),
uint16(1337),
uint16(1338),
_data
Expand Down
6 changes: 6 additions & 0 deletions contracts/mocks/Box.sol
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,10 @@ contract Box {
bytes memory encodedData = abi.encodeWithSelector(methodSelector, _i);
IAMB(_bridge).requireToPassMessage(_executor, encodedData, 141647);
}

function setValueOnOtherNetworkUsingManualLane(uint256 _i, address _bridge, address _executor) public {
bytes4 methodSelector = this.setValue.selector;
bytes memory encodedData = abi.encodeWithSelector(methodSelector, _i);
IAMB(_bridge).requireToConfirmMessage(_executor, encodedData, 141647);
}
}
7 changes: 7 additions & 0 deletions contracts/upgradeable_contracts/BaseFeeManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ contract BaseFeeManager is EternalStorage, FeeTypes {
bytes32 internal constant HOME_FEE_STORAGE_KEY = 0xc3781f3cec62d28f56efe98358f59c2105504b194242dbcb2cc0806850c306e7; // keccak256(abi.encodePacked("homeFee"))
bytes32 internal constant FOREIGN_FEE_STORAGE_KEY = 0x68c305f6c823f4d2fa4140f9cf28d32a1faccf9b8081ff1c2de11cf32c733efc; // keccak256(abi.encodePacked("foreignFee"))

/**
* @dev Calculated the amount of fee for the particular bridge operation.
* @param _value bridged amount of tokens/coins for which fee amount is calculated.
* @param _recover true, if the fee was already subtracted from the given _value and needs to be restored.
* @param _feeType type of the fee, should be either HOME_FEE of FOREIGN_FEE.
* @return calculated fee amount.
*/
function calculateFee(uint256 _value, bool _recover, bytes32 _feeType)
public
view
Expand Down
59 changes: 40 additions & 19 deletions contracts/upgradeable_contracts/BaseOverdrawManagement.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,63 @@ pragma solidity 0.4.24;

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

/**
* @title BaseOverdrawManagement
* @dev This contract implements basic functionality for tracking execution bridge operations that are out of limits.
*/
contract BaseOverdrawManagement is EternalStorage {
event AmountLimitExceeded(address recipient, uint256 value, bytes32 transactionHash);
event AssetAboveLimitsFixed(bytes32 indexed transactionHash, uint256 value, uint256 remaining);
event MediatorAmountLimitExceeded(address recipient, uint256 value, bytes32 indexed messageId);
event AmountLimitExceeded(address recipient, uint256 value, bytes32 indexed transactionHash, bytes32 messageId);
event AssetAboveLimitsFixed(bytes32 indexed messageId, uint256 value, uint256 remaining);

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

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

function fixedAssets(bytes32 _txHash) public view returns (bool) {
return boolStorage[keccak256(abi.encodePacked("fixedAssets", _txHash))];
}

/**
* @dev Internal function for updating a total amount that is out of execution limits.
* @param _value new value for the total amount of bridge operations above limits.
*/
function setOutOfLimitAmount(uint256 _value) internal {
uintStorage[OUT_OF_LIMIT_AMOUNT] = _value;
}

function txAboveLimits(bytes32 _txHash) internal view returns (address recipient, uint256 value) {
recipient = addressStorage[keccak256(abi.encodePacked("txOutOfLimitRecipient", _txHash))];
value = uintStorage[keccak256(abi.encodePacked("txOutOfLimitValue", _txHash))];
}

function setTxAboveLimits(address _recipient, uint256 _value, bytes32 _txHash) internal {
addressStorage[keccak256(abi.encodePacked("txOutOfLimitRecipient", _txHash))] = _recipient;
setTxAboveLimitsValue(_value, _txHash);
/**
* @dev Internal function for retrieving information about out-of-limits bridge operation.
* @param _messageId id of the message that cause above-limits error.
* @return (address of the receiver, amount of coins/tokens in the bridge operation)
*/
function txAboveLimits(bytes32 _messageId) internal view returns (address recipient, uint256 value) {
recipient = addressStorage[keccak256(abi.encodePacked("txOutOfLimitRecipient", _messageId))];
value = uintStorage[keccak256(abi.encodePacked("txOutOfLimitValue", _messageId))];
}

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

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

/* solcov ignore next */
function fixAssetsAboveLimits(bytes32 txHash, bool unlockOnForeign, uint256 valueToUnlock) external;
function fixAssetsAboveLimits(bytes32 messageId, bool unlockOnForeign, uint256 valueToUnlock) external;
}
25 changes: 18 additions & 7 deletions contracts/upgradeable_contracts/BasicHomeBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import "../libraries/Message.sol";
import "./BasicBridge.sol";
import "./BasicTokenBridge.sol";

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

Expand All @@ -21,9 +25,16 @@ contract BasicHomeBridge is EternalStorage, Validatable, BasicBridge, BasicToken
uint256 NumberOfCollectedSignatures
);

/**
* @dev Executes a message affirmation for some Foreign side event.
* Can be called only by a current bridge validator.
* @param recipient tokens/coins of receiver address, where the assets should be unlocked/minted.
* @param value amount of assets to unlock/mint.
* @param transactionHash reference event transaction hash on the Foreign side of the bridge.
*/
function executeAffirmation(address recipient, uint256 value, bytes32 transactionHash) external onlyValidator {
bytes32 hashMsg = keccak256(abi.encodePacked(recipient, value, transactionHash));
if (withinExecutionLimit(value)) {
bytes32 hashMsg = keccak256(abi.encodePacked(recipient, value, transactionHash));
bytes32 hashSender = keccak256(abi.encodePacked(msg.sender, hashMsg));
// Duplicated affirmations
require(!affirmationsSigned(hashSender));
Expand All @@ -43,12 +54,12 @@ contract BasicHomeBridge is EternalStorage, Validatable, BasicBridge, BasicToken
// it will couse funds lock on the home side of the bridge
setNumAffirmationsSigned(hashMsg, markAsProcessed(signed));
if (value > 0) {
require(onExecuteAffirmation(recipient, value, transactionHash));
require(onExecuteAffirmation(recipient, value, transactionHash, hashMsg));
}
emit AffirmationCompleted(recipient, value, transactionHash);
}
} else {
onFailedAffirmation(recipient, value, transactionHash);
onFailedAffirmation(recipient, value, transactionHash, hashMsg);
}
}

Expand Down Expand Up @@ -92,7 +103,10 @@ contract BasicHomeBridge is EternalStorage, Validatable, BasicBridge, BasicToken
}

/* solcov ignore next */
function onExecuteAffirmation(address, uint256, bytes32) internal returns (bool);
function onExecuteAffirmation(address, uint256, bytes32, bytes32) internal returns (bool);

/* solcov ignore next */
function onFailedAffirmation(address, uint256, bytes32, bytes32) internal;

/* solcov ignore next */
function onSignaturesCollected(bytes) internal;
Expand Down Expand Up @@ -153,7 +167,4 @@ contract BasicHomeBridge is EternalStorage, Validatable, BasicBridge, BasicToken
function requiredMessageLength() public pure returns (uint256) {
return Message.requiredMessageLength();
}

/* solcov ignore next */
function onFailedAffirmation(address, uint256, bytes32) internal;
}
64 changes: 64 additions & 0 deletions contracts/upgradeable_contracts/HomeOverdrawManagement.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
pragma solidity 0.4.24;

import "openzeppelin-solidity/contracts/math/SafeMath.sol";
import "./Upgradeable.sol";
import "./RewardableBridge.sol";
import "./BasicHomeBridge.sol";
import "./BaseOverdrawManagement.sol";

/**
* @title HomeOverdrawManagement
* @dev This contract implements functionality for recovering from out-of-limits executions in Home side vanilla bridges.
*/
contract HomeOverdrawManagement is BaseOverdrawManagement, RewardableBridge, Upgradeable, BasicHomeBridge {
using SafeMath for uint256;

/**
* @dev Fixes locked tokens, that were out of execution limits during the call to executeAffirmation.
* @param hashMsg reference for bridge operation that was out of execution limits.
* @param unlockOnForeign true if fixed tokens should be unlocked to the other side of the bridge.
* @param valueToUnlock unlocked amount of tokens, should be less than txAboveLimitsValue.
* Should be less than maxPerTx(), if tokens need to be unlocked on the other side.
*/
function fixAssetsAboveLimits(bytes32 hashMsg, bool unlockOnForeign, uint256 valueToUnlock)
external
onlyIfUpgradeabilityOwner
{
uint256 signed = numAffirmationsSigned(hashMsg);
require(!isAlreadyProcessed(signed));
(address recipient, uint256 value) = txAboveLimits(hashMsg);
require(recipient != address(0) && value > 0 && value >= valueToUnlock);
setOutOfLimitAmount(outOfLimitAmount().sub(valueToUnlock));
uint256 pendingValue = value.sub(valueToUnlock);
setTxAboveLimitsValue(pendingValue, hashMsg);
emit AssetAboveLimitsFixed(hashMsg, valueToUnlock, pendingValue);
if (unlockOnForeign) {
require(valueToUnlock <= maxPerTx());
address feeManager = feeManagerContract();
uint256 eventValue = valueToUnlock;
if (feeManager != address(0)) {
uint256 fee = calculateFee(valueToUnlock, false, feeManager, HOME_FEE);
eventValue = valueToUnlock.sub(fee);
}
emit UserRequestForSignature(recipient, eventValue);
}
}

/**
* @dev Internal function for clearing above limits markers for some failed transfer.
* Useful when transfer is being reprocessed on a new day or after limits were updated.
* It is required that fixAssetsAboveLimits was not called on the failed transfer before prior to this function.
* @param _hashMsg hash of the message, works as a unique indentifier.
* @param _value transferred amount of tokens/coins in the fixed message.
*/
function _clearAboveLimitsMarker(bytes32 _hashMsg, uint256 _value) internal {
(address aboveLimitsRecipient, uint256 aboveLimitsValue) = txAboveLimits(_hashMsg);
// check if transfer was marked as out of limits
if (aboveLimitsRecipient != address(0)) {
// revert if a given transaction hash was already processed by the call to fixAssetsAboveLimits
require(aboveLimitsValue == _value);
setTxAboveLimits(address(0), 0, _hashMsg);
setOutOfLimitAmount(outOfLimitAmount().sub(_value));
}
}
}
41 changes: 0 additions & 41 deletions contracts/upgradeable_contracts/OverdrawManagement.sol

This file was deleted.

Loading

0 comments on commit 835742d

Please sign in to comment.