Skip to content

Commit

Permalink
Merge the develop branch to the master branch, preparation to v1.0.0-rc0
Browse files Browse the repository at this point in the history
  • Loading branch information
akolotov committed Jan 15, 2021
2 parents e44a5f8 + 6014b7b commit c30d285
Show file tree
Hide file tree
Showing 64 changed files with 1,639 additions and 414 deletions.
3 changes: 2 additions & 1 deletion .eslintrc
Expand Up @@ -28,6 +28,7 @@
"global-require": "off",
"no-loop-func": "off",
"no-console": "off",
"node/no-missing-require": "off"
"node/no-missing-require": "off",
"import/no-unresolved": "off"
}
}
6 changes: 6 additions & 0 deletions .github/workflows/main.yml
Expand Up @@ -42,3 +42,9 @@ jobs:
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
e2e:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run tests
run: yarn e2e-tests:local
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -8,3 +8,4 @@ deploy/*.env*
!deploy/.env.example
deploy/bridgeDeploymentResults.json
coverage.json
e2e-tests/.env
4 changes: 3 additions & 1 deletion Dockerfile
Expand Up @@ -6,11 +6,12 @@ COPY package.json yarn.lock ./
RUN yarn

COPY truffle-config.js truffle-config.js
COPY ./precompiled ./precompiled
COPY ./contracts ./contracts
RUN yarn compile

COPY flatten.sh flatten.sh
RUN bash flatten.sh
RUN yarn flatten

FROM node:14

Expand All @@ -21,6 +22,7 @@ RUN yarn install --prod

COPY --from=contracts /contracts/build ./build
COPY --from=contracts /contracts/flats ./flats
COPY ./precompiled/PermittableToken.json ./precompiled/PermittableToken.json

COPY deploy.sh deploy.sh
COPY ./deploy ./deploy
Expand Down
4 changes: 3 additions & 1 deletion Dockerfile.dev
Expand Up @@ -6,14 +6,16 @@ COPY package.json yarn.lock ./
RUN yarn

COPY truffle-config.js truffle-config.js
COPY ./precompiled ./precompiled
COPY ./contracts ./contracts
RUN yarn compile

COPY flatten.sh flatten.sh
RUN bash flatten.sh
RUN yarn flatten

COPY deploy.sh deploy.sh
COPY ./deploy ./deploy
COPY ./test ./test
COPY ./e2e-tests ./e2e-tests

ENV PATH="/contracts/:${PATH}"
10 changes: 10 additions & 0 deletions contracts/interfaces/IAMB.sol
@@ -1,6 +1,16 @@
pragma solidity 0.7.5;

interface IAMB {
event UserRequestForAffirmation(bytes32 indexed messageId, bytes encodedData);
event UserRequestForSignature(bytes32 indexed messageId, bytes encodedData);
event AffirmationCompleted(
address indexed sender,
address indexed executor,
bytes32 indexed messageId,
bool status
);
event RelayedMessage(address indexed sender, address indexed executor, bytes32 indexed messageId, bool status);

function messageSender() external view returns (address);

function maxGasPerTx() external view returns (uint256);
Expand Down
9 changes: 9 additions & 0 deletions contracts/interfaces/IERC20Metadata.sol
@@ -0,0 +1,9 @@
pragma solidity 0.7.5;

interface IERC20Metadata {
function name() external view returns (string memory);

function symbol() external view returns (string memory);

function decimals() external view returns (uint8);
}
@@ -1,9 +1,9 @@
pragma solidity 0.7.5;

import "@openzeppelin/contracts/math/SafeMath.sol";
import "../Initializable.sol";
import "../Upgradeable.sol";
import "../Claimable.sol";
import "./Initializable.sol";
import "./Upgradeable.sol";
import "./Claimable.sol";
import "./components/bridged/BridgedTokensRegistry.sol";
import "./components/native/NativeTokensRegistry.sol";
import "./components/native/MediatorBalanceStorage.sol";
Expand All @@ -12,14 +12,15 @@ import "./components/common/OmnibridgeInfo.sol";
import "./components/common/TokensBridgeLimits.sol";
import "./components/common/FailedMessagesProcessor.sol";
import "./modules/factory/TokenFactoryConnector.sol";
import "../../interfaces/IBurnableMintableERC677Token.sol";
import "../../libraries/TokenReader.sol";
import "../interfaces/IBurnableMintableERC677Token.sol";
import "../interfaces/IERC20Metadata.sol";
import "../libraries/TokenReader.sol";

/**
* @title BasicMultiAMBErc20ToErc677
* @dev Common functionality for universal multi-erc20-to-erc677 mediator intended to work on top of AMB bridge.
* @title BasicOmnibridge
* @dev Common functionality for multi-token mediator intended to work on top of AMB bridge.
*/
abstract contract BasicMultiAMBErc20ToErc677 is
abstract contract BasicOmnibridge is
Initializable,
Upgradeable,
Claimable,
Expand Down Expand Up @@ -67,6 +68,9 @@ abstract contract BasicMultiAMBErc20ToErc677 is
bridgedToken = tokenFactory().deploy(name, symbol, _decimals, bridgeContract().sourceChainId());
_setTokenAddressPair(_token, bridgedToken);
_initToken(bridgedToken, _decimals);
} else if (!isTokenRegistered(bridgedToken)) {
require(IERC20Metadata(bridgedToken).decimals() == _decimals);
_initToken(bridgedToken, _decimals);
}

_handleTokens(bridgedToken, false, _recipient, _value);
Expand Down Expand Up @@ -123,8 +127,7 @@ abstract contract BasicMultiAMBErc20ToErc677 is
) internal override {
bytes32 registrationMessageId = tokenRegistrationMessageId(_token);
if (registrationMessageId != bytes32(0)) {
IERC677(_token).safeTransfer(_recipient, _value);
_setMediatorBalance(_token, mediatorBalance(_token).sub(_value));
_releaseTokens(_token, _recipient, _value);
if (_messageId == registrationMessageId) {
delete uintStorage[keccak256(abi.encodePacked("dailyLimit", _token))];
delete uintStorage[keccak256(abi.encodePacked("maxPerTx", _token))];
Expand All @@ -134,10 +137,27 @@ abstract contract BasicMultiAMBErc20ToErc677 is
_setTokenRegistrationMessageId(_token, bytes32(0));
}
} else {
IBurnableMintableERC677Token(_token).mint(_recipient, _value);
_getMinterFor(_token).mint(_recipient, _value);
}
}

/**
* @dev Allows to pre-set the bridged token contract for not-yet bridged token.
* Only the owner can call this method.
* @param _nativeToken address of the token contract on the other side that was not yet bridged.
* @param _bridgedToken address of the bridged token contract.
*/
function setCustomTokenAddressPair(address _nativeToken, address _bridgedToken) external onlyOwner {
require(!isTokenRegistered(_bridgedToken));
require(nativeTokenAddress(_bridgedToken) == address(0));
require(bridgedTokenAddress(_nativeToken) == address(0));

IBurnableMintableERC677Token(_bridgedToken).mint(address(this), 1);
IBurnableMintableERC677Token(_bridgedToken).burn(1);

_setTokenAddressPair(_nativeToken, _bridgedToken);
}

/**
* @dev Allows to send to the other network the amount of locked tokens that can be forced into the contract
* without the invocation of the required methods. (e. g. regular transfer without a call to onTokenTransfer)
Expand Down Expand Up @@ -266,6 +286,30 @@ abstract contract BasicMultiAMBErc20ToErc677 is
_initializeTokenBridgeLimits(_token, _decimals);
}

/**
* @dev Internal function for getting minter proxy address.
* @param _token address of the token to mint.
* @return address of the minter contract that should be used for calling mint(address,uint256)
*/
function _getMinterFor(address _token) internal view virtual returns (IBurnableMintableERC677Token) {
return IBurnableMintableERC677Token(_token);
}

/**
* Internal function for unlocking some amount of tokens.
* @param _token address of the token contract.
* @param _recipient address of the tokens receiver.
* @param _value amount of tokens to unlock.
*/
function _releaseTokens(
address _token,
address _recipient,
uint256 _value
) internal virtual {
IERC677(_token).safeTransfer(_recipient, _value);
_setMediatorBalance(_token, mediatorBalance(_token).sub(_value));
}

function _handleTokens(
address _token,
bool _isNative,
Expand Down
@@ -1,13 +1,13 @@
pragma solidity 0.7.5;

import "./BasicMultiAMBErc20ToErc677.sol";
import "./BasicOmnibridge.sol";

/**
* @title ForeignMultiAMBErc20ToErc677
* @dev Foreign side implementation for multi-erc20-to-erc677 mediator intended to work on top of AMB bridge.
* @title ForeignOmnibridge
* @dev Foreign side implementation for multi-token mediator intended to work on top of AMB bridge.
* It is designed to be used as an implementation contract of EternalStorageProxy contract.
*/
contract ForeignMultiAMBErc20ToErc677 is BasicMultiAMBErc20ToErc677 {
contract ForeignOmnibridge is BasicOmnibridge {
using SafeERC20 for IERC677;
using SafeMath for uint256;

Expand Down Expand Up @@ -47,6 +47,17 @@ contract ForeignMultiAMBErc20ToErc677 is BasicMultiAMBErc20ToErc677 {
return isInitialized();
}

/**
* One-time function to be used together with upgradeToAndCall method.
* Sets the token factory contract.
* @param _tokenFactory address of the deployed TokenFactory contract.
*/
function upgradeToReverseMode(address _tokenFactory) external {
require(msg.sender == address(this));

_setTokenFactory(_tokenFactory);
}

/**
* @dev Handles the bridged tokens.
* Checks that the value is inside the execution limits and invokes the Mint or Unlock accordingly.
Expand All @@ -65,10 +76,9 @@ contract ForeignMultiAMBErc20ToErc677 is BasicMultiAMBErc20ToErc677 {
addTotalExecutedPerDay(_token, getCurrentDay(), _value);

if (_isNative) {
IERC677(_token).safeTransfer(_recipient, _value);
_setMediatorBalance(_token, mediatorBalance(_token).sub(_value));
_releaseTokens(_token, _recipient, _value);
} else {
IBurnableMintableERC677Token(_token).mint(_recipient, _value);
_getMinterFor(_token).mint(_recipient, _value);
}

emit TokensBridged(_token, _recipient, _value, messageId());
Expand Down Expand Up @@ -106,6 +116,38 @@ contract ForeignMultiAMBErc20ToErc677 is BasicMultiAMBErc20ToErc677 {
_recordBridgeOperation(!isKnownToken, _messageId, _token, _from, _value);
}

/**
* Internal function for unlocking some amount of tokens.
* When bridging STAKE token, the insufficient amount of tokens can be additionally minted.
* @param _token address of the token contract.
* @param _recipient address of the tokens receiver.
* @param _value amount of tokens to unlock.
*/
function _releaseTokens(
address _token,
address _recipient,
uint256 _value
) internal override {
uint256 balance = mediatorBalance(_token);

// STAKE total supply on xDai can be higher than the native STAKE supply on Mainnet
// Omnibridge is allowed to mint extra native STAKE tokens.
if (_token == address(0x0Ae055097C6d159879521C384F1D2123D1f195e6) && balance < _value) {
// if all locked tokens were already withdrawn, mint new tokens directly to receiver
// mediatorBalance(STAKE) remains 0 in this case.
if (balance == 0) {
IBurnableMintableERC677Token(_token).mint(_recipient, _value);
return;
}

// otherwise, first mint insufficient tokens to the contract
IBurnableMintableERC677Token(_token).mint(address(this), _value - balance);
balance = _value;
}
IERC677(_token).safeTransfer(_recipient, _value);
_setMediatorBalance(_token, balance.sub(_value));
}

/**
* @dev Internal function for transforming the bridged token name. Appends a side-specific suffix.
* @param _name bridged token from the other side.
Expand Down

0 comments on commit c30d285

Please sign in to comment.