Lachain ERC20 handler

Contract

// pragma solidity 0.6.4;
pragma experimental ABIEncoderV2;
import "../interfaces/IDepositExecute.sol";
import "../interfaces/IERC20.sol";
import "./HandlerHelpers.sol";
import "../ERC20Safe.sol";
import "../ExampleToken.sol";
import "../utils/UpgradableOwnable.sol";
/**
    @title Handles ERC20 deposits and deposit executions.
    @notice This contract is intended to be used with the Bridge contract.
 */
contract ERC20Handler is
    IDepositExecute,
    HandlerHelpers,
    UpgradableOwnable,
    ERC20Safe
{
    struct DepositRecord {
        address _tokenAddress;
        bytes8 _destinationChainID;
        bytes32 _resourceID;
        address _destinationRecipientAddress;
        address _depositer;
        uint256 _amount;
    }
    // depositNonce => Deposit Record
    mapping(bytes8 => mapping(uint64 => DepositRecord)) public _depositRecords;
    /**
        @param bridgeAddress Contract address of previously deployed Bridge.
     */
    function initialize(address bridgeAddress) public {
        _bridgeAddress = bridgeAddress;
        ownableInit(msg.sender);
    }
    function adminChangeBridgeAddress(address newBridgeAddress)
        external
        onlyOwner
        isInitisalised
    {
        _bridgeAddress = newBridgeAddress;
    }
    /**
        @param depositNonce This ID will have been generated by the Bridge contract.
        @param destId ID of chain deposit will be bridged to.
        @return DepositRecord which consists of:
        - _tokenAddress Address used when {deposit} was executed.
        - _destinationChainID ChainID deposited tokens are intended to end up on.
        - _resourceID ResourceID used when {deposit} was executed.
        - _destinationRecipientAddress Address tokens are intended to be deposited to on desitnation chain.
        - _depositer Address that initially called {deposit} in the Bridge contract.
        - _amount Amount of tokens that were deposited.
    */
    function getDepositRecord(uint64 depositNonce, bytes8 destId)
        external
        view
        isInitisalised
        returns (DepositRecord memory)
    {
        return _depositRecords[destId][depositNonce];
    }
    /**
        @notice A deposit is initiatied by making a deposit in the Bridge contract.
        @param destinationChainID Chain ID of chain tokens are expected to be bridged to.
        @param depositNonce This value is generated as an ID by the Bridge contract.
        @param depositer Address of account making the deposit in the Bridge contract.
        @notice Data passed into the function should be constructed as follows:
        amount                      uint256     bytes   0 - 32
        recipientAddress length     uint256     bytes  32 - 64
        recipientAddress            bytes       bytes  64 - END
        @dev Depending if the corresponding {tokenAddress} for the parsed {resourceID} is
        marked true in {_burnList}, deposited tokens will be burned, if not, they will be locked.
     */
    function deposit(
        bytes32 resourceID,
        bytes8 destinationChainID,
        uint64 depositNonce,
        address depositer,
        address recipientAddress,
        uint256 amount,
        bytes calldata params
    ) external override onlyBridge isInitisalised returns (address) {
        // bytes memory recipientAddress;
        // uint256 amount;
        // uint256 lenRecipientAddress;
        // assembly {
        //     amount := calldataload(0xC4)
        //     recipientAddress := mload(0x40)
        //     lenRecipientAddress := calldataload(0xE4)
        //     mstore(0x40, add(0x20, add(recipientAddress, lenRecipientAddress)))
        //     calldatacopy(
        //         recipientAddress, // copy to destinationRecipientAddress
        //         0xE4, // copy from calldata @ 0x104
        //         sub(calldatasize(), 0xE) // copy size (calldatasize - 0x104)
        //     )
        // }
        address tokenAddress = _resourceIDToTokenContractAddress[resourceID];
        require(
            _contractWhitelist[tokenAddress],
            "provided tokenAddress is not whitelisted"
        );
        if (_burnList[tokenAddress]) {
            burnERC20(tokenAddress, depositer, amount);
        } else {
            lockERC20(tokenAddress, depositer, address(this), amount);
        }
        _depositRecords[destinationChainID][depositNonce] = DepositRecord(
            tokenAddress,
            destinationChainID,
            resourceID,
            recipientAddress,
            depositer,
            amount
        );
        return (tokenAddress);
    }
    /**
        @notice Proposal execution should be initiated when a proposal is finalized in the Bridge contract.
        by a relayer on the deposit's destination chain.
        @notice Data passed into the function should be constructed as follows:
        amount                                 uint256     bytes  0 - 32
        destinationRecipientAddress length     uint256     bytes  32 - 64
        destinationRecipientAddress            bytes       bytes  64 - END
     */
    function executeProposal(
        bytes32 resourceID,
        address recipientAddress,
        uint256 amount,
        bytes calldata params
    ) external override onlyBridge isInitisalised {
        // uint256 amount;
        // bytes memory destinationRecipientAddress;
        // assembly {
        //     amount := calldataload(0x64)
        //     destinationRecipientAddress := mload(0x40)
        //     let lenDestinationRecipientAddress := calldataload(0x84)
        //     mstore(
        //         0x40,
        //         add(
        //             0x20,
        //             add(
        //                 destinationRecipientAddress,
        //                 lenDestinationRecipientAddress
        //             )
        //         )
        //     )
        //     // in the calldata the destinationRecipientAddress is stored at 0xC4 after accounting for the function signature and length declaration
        //     calldatacopy(
        //         destinationRecipientAddress, // copy to destinationRecipientAddress
        //         0x84, // copy from calldata @ 0x84
        //         sub(calldatasize(), 0x84) // copy size to the end of calldata
        //     )
        // }
        // bytes20 recipientAddress;
        address tokenAddress = _resourceIDToTokenContractAddress[resourceID];
        // assembly {
        //     recipientAddress := mload(add(destinationRecipientAddress, 0x20))
        // }
        require(
            _contractWhitelist[tokenAddress],
            "provided tokenAddress is not whitelisted"
        );
        if (_burnList[tokenAddress]) {
            mintERC20(tokenAddress, recipientAddress, amount);
        } else {
            releaseERC20(tokenAddress, recipientAddress, amount);
        }
    }
    /**
        @notice Used to manually release ERC20 tokens from ERC20Safe.
        @param tokenAddress Address of token contract to release.
        @param recipient Address to release tokens to.
        @param amount The amount of ERC20 tokens to release.
     */
    function withdraw(
        address tokenAddress,
        address recipient,
        uint256 amount
    ) external override onlyBridge isInitisalised {
        releaseERC20(tokenAddress, recipient, amount);
    }
    function getAddressFromResourceId(bytes32 resourceID)
        external
        view
        override
        returns (address)
    {
        return _resourceIDToTokenContractAddress[resourceID];
    }
    /**
        @notice Used to approve spending tokens.
        @param resourceID ResourceID to be used for approval.
        @param spender Spender address.
        @param amount Amount to approve.
     */
    function approve(
        bytes32 resourceID,
        address spender,
        uint256 amount
    ) external override onlyBridge isInitisalised {
        address tokenAddress = _resourceIDToTokenContractAddress[resourceID];
        require(
            _contractWhitelist[tokenAddress],
            "provided tokenAddress is not whitelisted"
        );
        approveERC20(tokenAddress, spender, amount);
    }
}

Last updated