Skip to content
This repository has been archived by the owner on May 9, 2024. It is now read-only.

Commit

Permalink
Merge branch 'master' into anthony/deployBytecodeRemoval
Browse files Browse the repository at this point in the history
  • Loading branch information
ansermino committed Apr 28, 2020
2 parents 1cec1db + 5c4c4cd commit a027ee1
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 147 deletions.
26 changes: 13 additions & 13 deletions contracts/Bridge.sol
Expand Up @@ -152,8 +152,8 @@ contract Bridge is Pausable, AccessControl {
handler.setBurnable(tokenAddress);
}

function getProposal(uint8 originChainID, uint256 depositNonce) public view returns (Proposal memory) {
return _proposals[originChainID][depositNonce];
function getProposal(uint8 chainID, uint256 depositNonce) public view returns (Proposal memory) {
return _proposals[chainID][depositNonce];
}

// Initiates a transfer accros the bridge by calling the specified handler
Expand All @@ -167,40 +167,40 @@ contract Bridge is Pausable, AccessControl {
emit Deposit(destinationChainID, handler, depositNonce);
}

function voteProposal(uint8 originChainID, uint256 depositNonce, bytes32 dataHash) public onlyRelayers whenNotPaused {
Proposal storage proposal = _proposals[uint8(originChainID)][depositNonce];
function voteProposal(uint8 chainID, uint256 depositNonce, bytes32 dataHash) public onlyRelayers whenNotPaused {
Proposal storage proposal = _proposals[uint8(chainID)][depositNonce];

require(uint(proposal._status) <= 1, "proposal has already been passed or transferred");
require(!_hasVotedOnProposal[originChainID][depositNonce][msg.sender], "relayer has already voted on proposal");
require(!_hasVotedOnProposal[chainID][depositNonce][msg.sender], "relayer has already voted on proposal");

if (uint(proposal._status) == 0) {
++_totalProposals;
_proposals[originChainID][depositNonce] = Proposal({
_proposals[chainID][depositNonce] = Proposal({
_dataHash: dataHash,
_yesVotes: new address[](1),
_noVotes: new address[](0),
_status: ProposalStatus.Active
});

proposal._yesVotes[0] = msg.sender;
emit ProposalCreated(originChainID, _chainID, depositNonce, dataHash);
emit ProposalCreated(chainID, _chainID, depositNonce, dataHash);
} else {
proposal._yesVotes.push(msg.sender);
}

_hasVotedOnProposal[originChainID][depositNonce][msg.sender] = true;
emit ProposalVote(originChainID, _chainID, depositNonce, proposal._status);
_hasVotedOnProposal[chainID][depositNonce][msg.sender] = true;
emit ProposalVote(chainID, _chainID, depositNonce, proposal._status);

// If _depositThreshold is set to 1, then auto finalize
// or if _relayerThreshold has been exceeded
if (_relayerThreshold <= 1 || proposal._yesVotes.length >= _relayerThreshold) {
proposal._status = ProposalStatus.Passed;
emit ProposalFinalized(originChainID, _chainID, depositNonce);
emit ProposalFinalized(chainID, _chainID, depositNonce);
}
}

function executeProposal(uint8 originChainID, uint256 depositNonce, address handler, bytes memory data) public onlyRelayers whenNotPaused {
Proposal storage proposal = _proposals[uint8(originChainID)][depositNonce];
function executeProposal(uint8 chainID, uint256 depositNonce, address handler, bytes memory data) public onlyRelayers whenNotPaused {
Proposal storage proposal = _proposals[uint8(chainID)][depositNonce];

require(proposal._status != ProposalStatus.Inactive, "proposal is not active");
require(proposal._status == ProposalStatus.Passed, "proposal was not passed or has already been transferred");
Expand All @@ -211,6 +211,6 @@ contract Bridge is Pausable, AccessControl {
depositHandler.executeDeposit(data);
proposal._status = ProposalStatus.Transferred;
emit ProposalExecuted(originChainID, _chainID, depositNonce);
emit ProposalExecuted(chainID, _chainID, depositNonce);
}
}
71 changes: 11 additions & 60 deletions contracts/handlers/ERC20Handler.sol
@@ -1,17 +1,16 @@
pragma solidity 0.6.4;
pragma experimental ABIEncoderV2;

import "../interfaces/IDepositExecute.sol";
import "./HandlerHelpers.sol";
import "../ERC20Safe.sol";
import "@openzeppelin/contracts/presets/ERC20PresetMinterPauser.sol";
import "../interfaces/IDepositExecute.sol";
import "../interfaces/IERCHandler.sol";

contract ERC20Handler is IDepositExecute, IERCHandler, ERC20Safe {
address public _bridgeAddress;
contract ERC20Handler is IDepositExecute, HandlerHelpers, ERC20Safe {
bool public _useContractWhitelist;

struct DepositRecord {
address _originChainTokenAddress;
address _tokenAddress;
uint8 _destinationChainID;
bytes32 _resourceID;
uint _lenDestinationRecipientAddress;
Expand All @@ -20,26 +19,9 @@ contract ERC20Handler is IDepositExecute, IERCHandler, ERC20Safe {
uint _amount;
}

// resourceID => token contract address
mapping (bytes32 => address) public _resourceIDToTokenContractAddress;

// token contract address => resourceID
mapping (address => bytes32) public _tokenContractAddressToResourceID;

// token contract address => is whitelisted
mapping (address => bool) public _contractWhitelist;

// token contract address => is burnable
mapping (address => bool) public _burnList;

// depositNonce => Deposit Record
mapping (uint256 => DepositRecord) public _depositRecords;

modifier _onlyBridge() {
require(msg.sender == _bridgeAddress, "sender must be bridge contract");
_;
}

constructor(
address bridgeAddress,
bytes32[] memory initialResourceIDs,
Expand All @@ -64,37 +46,6 @@ contract ERC20Handler is IDepositExecute, IERCHandler, ERC20Safe {
return _depositRecords[depositID];
}

function isWhitelisted(address contractAddress) public view returns (bool) {
return _contractWhitelist[contractAddress];
}

function setBurnable(address contractAddress) public override _onlyBridge {
_setBurnable(contractAddress);
}

function _setBurnable(address contractAddress) internal {
require(isWhitelisted(contractAddress), "provided contract is not whitelisted");
_burnList[contractAddress] = true;
}

function _setResource(bytes32 resourceID, address contractAddress) internal {
_resourceIDToTokenContractAddress[resourceID] = contractAddress;
_tokenContractAddressToResourceID[contractAddress] = resourceID;

_contractWhitelist[contractAddress] = true;
}

function setResource(bytes32 resourceID, address contractAddress) public override _onlyBridge {
require(_resourceIDToTokenContractAddress[resourceID] == address(0), "resourceID already has a corresponding contract address");

bytes32 currentResourceID = _tokenContractAddressToResourceID[contractAddress];
bytes32 emptyBytes;
require(keccak256(abi.encodePacked((currentResourceID))) == keccak256(abi.encodePacked((emptyBytes))),
"contract address already has corresponding resourceID");

_setResource(resourceID, contractAddress);
}

// Initiate a transfer by completing a deposit (transferFrom).
// Data passed into the function should be constructed as follows:
//
Expand Down Expand Up @@ -129,17 +80,17 @@ contract ERC20Handler is IDepositExecute, IERCHandler, ERC20Safe {
)
}

address originTokenAddress = _resourceIDToTokenContractAddress[resourceID];
require(isWhitelisted(originTokenAddress), "provided originTokenAddress is not whitelisted");
address tokenAddress = _resourceIDToTokenContractAddress[resourceID];
require(_contractWhitelist[tokenAddress], "provided tokenAddress is not whitelisted");

if (_burnList[originTokenAddress]) {
burnERC20(originTokenAddress, depositer, amount);
if (_burnList[tokenAddress]) {
burnERC20(tokenAddress, depositer, amount);
} else {
lockERC20(originTokenAddress, depositer, address(this), amount);
lockERC20(tokenAddress, depositer, address(this), amount);
}

_depositRecords[depositNonce] = DepositRecord(
originTokenAddress,
tokenAddress,
destinationChainID,
resourceID,
lenRecipientAddress,
Expand Down Expand Up @@ -186,7 +137,7 @@ contract ERC20Handler is IDepositExecute, IERCHandler, ERC20Safe {
recipientAddress := mload(add(destinationRecipientAddress, 0x20))
}

require(isWhitelisted(tokenAddress), "provided tokenAddress is not whitelisted");
require(_contractWhitelist[tokenAddress], "provided tokenAddress is not whitelisted");

if (_burnList[tokenAddress]) {
mintERC20(tokenAddress, address(recipientAddress), amount);
Expand Down
88 changes: 14 additions & 74 deletions contracts/handlers/ERC721Handler.sol
@@ -1,21 +1,21 @@
pragma solidity 0.6.4;
pragma experimental ABIEncoderV2;

import "../ERC721Safe.sol";
import "../interfaces/IDepositExecute.sol";
import "./HandlerHelpers.sol";
import "../ERC721Safe.sol";
import "../ERC721MinterBurnerPauser.sol";
import "../interfaces/IERCHandler.sol";
import "@openzeppelin/contracts/introspection/ERC165Checker.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol";

contract ERC721Handler is IDepositExecute, IERCHandler, ERC721Safe {
contract ERC721Handler is IDepositExecute, HandlerHelpers, ERC721Safe {
using ERC165Checker for address;
address public _bridgeAddress;
// address public _bridgeAddress;

bytes4 private constant _INTERFACE_ERC721_METADATA = 0x5b5e139f;

struct DepositRecord {
address _originChainTokenAddress;
address _tokenAddress;
uint8 _destinationChainID;
bytes32 _resourceID;
uint _lenDestinationRecipientAddress;
Expand All @@ -28,23 +28,6 @@ contract ERC721Handler is IDepositExecute, IERCHandler, ERC721Safe {
// DepositID => Deposit Record
mapping (uint256 => DepositRecord) public _depositRecords;

// resourceID => token contract address
mapping (bytes32 => address) public _resourceIDToTokenContractAddress;

// token contract address => resourceID
mapping (address => bytes32) public _tokenContractAddressToResourceID;

// token contract address => is whitelisted
mapping (address => bool) public _contractWhitelist;

// token contract address => is burnable
mapping (address => bool) public _burnList;

modifier _onlyBridge() {
require(msg.sender == _bridgeAddress, "sender must be bridge contract");
_;
}

constructor(
address bridgeAddress,
bytes32[] memory initialResourceIDs,
Expand All @@ -65,53 +48,10 @@ contract ERC721Handler is IDepositExecute, IERCHandler, ERC721Safe {
}
}

function isWhitelisted(address contractAddress) internal view returns (bool) {
return _contractWhitelist[contractAddress];
}

function getDepositRecord(uint256 depositID) public view returns (DepositRecord memory) {
return _depositRecords[depositID];
}

function setBurnable(address contractAddress) public override _onlyBridge{
_setBurnable(contractAddress);
}

function _setBurnable(address contractAddress) internal {
require(isWhitelisted(contractAddress), "provided contract is not whitelisted");
_burnList[contractAddress] = true;
}

function createResourceID (address originChainTokenAddress, uint8 chainID) internal pure returns (bytes32) {
bytes11 padding;
bytes memory encodedResourceID = abi.encodePacked(padding, abi.encodePacked(originChainTokenAddress, chainID));
bytes32 resourceID;

assembly {
resourceID := mload(add(encodedResourceID, 0x20))
}

return resourceID;
}

function _setResource(bytes32 resourceID, address contractAddress) internal {
_resourceIDToTokenContractAddress[resourceID] = contractAddress;
_tokenContractAddressToResourceID[contractAddress] = resourceID;

_contractWhitelist[contractAddress] = true;
}

function setResource(bytes32 resourceID, address contractAddress) public override _onlyBridge {
require(_resourceIDToTokenContractAddress[resourceID] == address(0), "resourceID already has a corresponding contract address");

bytes32 currentResourceID = _tokenContractAddressToResourceID[contractAddress];
bytes32 emptyBytes;
require(keccak256(abi.encodePacked((currentResourceID))) == keccak256(abi.encodePacked((emptyBytes))),
"contract address already has corresponding resourceID");

_setResource(resourceID, contractAddress);
}

// Make a deposit
// bytes memory data passed into the function should be constructed as follows:
//
Expand Down Expand Up @@ -152,23 +92,23 @@ contract ERC721Handler is IDepositExecute, IERCHandler, ERC721Safe {
)
}

address originChainTokenAddress = _resourceIDToTokenContractAddress[resourceID];
require(isWhitelisted(originChainTokenAddress), "provided originChainTokenAddress is not whitelisted");
address tokenAddress = _resourceIDToTokenContractAddress[resourceID];
require(_contractWhitelist[tokenAddress], "provided tokenAddress is not whitelisted");

// Check if the contract supports metadata, fetch it if it does
if (originChainTokenAddress.supportsInterface(_INTERFACE_ERC721_METADATA)) {
IERC721Metadata erc721 = IERC721Metadata(originChainTokenAddress);
if (tokenAddress.supportsInterface(_INTERFACE_ERC721_METADATA)) {
IERC721Metadata erc721 = IERC721Metadata(tokenAddress);
metaData = bytes(erc721.tokenURI(tokenID));
}

if (_burnList[originChainTokenAddress]) {
burnERC721(originChainTokenAddress, tokenID);
if (_burnList[tokenAddress]) {
burnERC721(tokenAddress, tokenID);
} else {
lockERC721(originChainTokenAddress, depositer, address(this), tokenID);
lockERC721(tokenAddress, depositer, address(this), tokenID);
}

_depositRecords[depositNonce] = DepositRecord(
originChainTokenAddress,
tokenAddress,
uint8(destinationChainID),
resourceID,
lenDestinationRecipientAddress,
Expand Down Expand Up @@ -243,7 +183,7 @@ contract ERC721Handler is IDepositExecute, IERCHandler, ERC721Safe {
}

address tokenAddress = _resourceIDToTokenContractAddress[resourceID];
require(isWhitelisted(address(tokenAddress)), "provided tokenAddress is not whitelisted");
require(_contractWhitelist[address(tokenAddress)], "provided tokenAddress is not whitelisted");

if (_burnList[tokenAddress]) {
mintERC721(tokenAddress, address(recipientAddress), tokenID, metaData);
Expand Down

0 comments on commit a027ee1

Please sign in to comment.