From 3a39a9ecb57ed6619860b6eaa8b05fbb0a83b6c6 Mon Sep 17 00:00:00 2001 From: filip Date: Fri, 1 Dec 2023 15:11:24 +0100 Subject: [PATCH] apply lints --- eth/contracts/Membrane.sol | 533 ++++++++++++++++++++----------------- 1 file changed, 292 insertions(+), 241 deletions(-) diff --git a/eth/contracts/Membrane.sol b/eth/contracts/Membrane.sol index 561cc465d..393bb3615 100644 --- a/eth/contracts/Membrane.sol +++ b/eth/contracts/Membrane.sol @@ -5,268 +5,319 @@ pragma solidity ^0.8; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; contract Membrane { - uint256 constant DIX_MILLE = 10000; - - address public owner; - uint256 public requestNonce; - /* uint256 public signatureThreshold; */ - uint256 public commissionPerDixMille; - uint256 public minimumTransferAmountUsd; - uint256 public committeeId; - bytes32 public USDT = 0x1000000000000000000000000000000000000000000000000000000000000000; - - struct Request { - uint256 signatureCount; - mapping(address => bool) signatures; - } - - // from -> to mapping - mapping(bytes32 => bytes32) public supportedPairs; - mapping(bytes32 => Request) public pendingRequests; - mapping(bytes32 => bool) public processedRequests; - mapping(bytes32 => bool) private committee; - mapping(uint256 => uint256) public committeeSize; - mapping(uint256 => uint256) public signatureThreshold; - mapping(bytes32 => uint256) private collectedCommitteeRewards; - mapping(bytes32 => uint256) private paidOutMemberRewards; - - event CrosschainTransferRequest( - uint256 indexed committeeId, - bytes32 indexed destTokenAddress, - uint256 amount, - bytes32 indexed destReceiverAddress, - uint256 requestNonce - ); - - event RequestSigned( - bytes32 requestHash, - address signer - ); - - event RequestProcessed(bytes32 requestHash); - - modifier _onlyOwner() { - require(msg.sender == owner); - _; - } - - modifier _onlyCurrentCommitteeMember() { - require(isInCommittee(committeeId, msg.sender), "NotInCommittee"); - _; - } - - constructor( - address[] memory _committee, - uint256 _signatureThreshold, - uint256 _commissionPerDixMille, - uint256 _minimumTransferAmountUsd - ) { - require(_signatureThreshold > 0, "Signature threshold must be greater than 0"); - require(_committee.length >= _signatureThreshold, "Not enough guardians specified"); - - owner = msg.sender; - commissionPerDixMille = _commissionPerDixMille; - minimumTransferAmountUsd = _minimumTransferAmountUsd; - committeeId = 0; - - for (uint256 i = 0; i < _committee.length; i++) { - committee[keccak256(abi.encodePacked(committeeId, _committee[i]))] = true; + uint256 constant DIX_MILLE = 10000; + + address public owner; + uint256 public requestNonce; + /* uint256 public signatureThreshold; */ + uint256 public commissionPerDixMille; + uint256 public minimumTransferAmountUsd; + uint256 public committeeId; + bytes32 public USDT = 0x1000000000000000000000000000000000000000000000000000000000000000; + + struct Request { + uint256 signatureCount; + mapping(address => bool) signatures; } - committeeSize [committeeId] = _committee.length; - signatureThreshold [committeeId] = _signatureThreshold; - - } - - // Invoke this tx to transfer funds to the destination chain. - // Account needs to approve the Membrane contract to spend the `srcTokenAmount` - // of `srcTokenAddress` tokens on their behalf before executing the tx. - // - // Tx emits a CrosschainTransferRequest event that the relayers listen to - // & forward to the destination chain. - function sendRequest( - bytes32 srcTokenAddress, - uint256 amount, - bytes32 destReceiverAddress - ) external { - - require(queryPrice(amount, srcTokenAddress, USDT) > minimumTransferAmountUsd, "AmountBelowMinimum"); - - address sender = msg.sender; - - IERC20 token = IERC20(bytes32ToAddress(srcTokenAddress)); - - // check if the token is supported - bytes32 destTokenAddress = supportedPairs[srcTokenAddress]; - require(destTokenAddress != 0x0, "Unsupported pair"); - - // lock tokens in this contract - // message sender needs to give approval else this tx will revert - token.transferFrom(sender, address(this), amount); - - emit CrosschainTransferRequest(committeeId, - destTokenAddress, - amount, - destReceiverAddress, - requestNonce); - - requestNonce++; - } - - // aggregates relayer signatures and returns the locked tokens - function receiveRequest( - bytes32 _requestHash, - bytes32 destTokenAddress, - uint256 amount, - bytes32 destReceiverAddress, - uint256 _requestNonce - ) external _onlyCurrentCommitteeMember { - require(!processedRequests[_requestHash], "This request has already been processed"); - - bytes32 requestHash = keccak256(abi.encodePacked(destTokenAddress, - amount, - destReceiverAddress, - _requestNonce)); - - require(_requestHash == requestHash, - "Hash does not match the data"); - - Request storage request = pendingRequests[requestHash]; - require(!request.signatures[msg.sender], "This guardian has already signed this request"); - - request.signatures[msg.sender] = true; - request.signatureCount++; - - emit RequestSigned(requestHash, msg.sender); - - if (request.signatureCount >= signatureThreshold[committeeId]) { - uint256 commission = (amount * commissionPerDixMille) / DIX_MILLE; - - collectedCommitteeRewards [keccak256(abi.encodePacked(committeeId, destTokenAddress))] += commission; - - processedRequests[requestHash] = true; - delete pendingRequests[requestHash]; - - // return the locked tokens - IERC20 token = IERC20(bytes32ToAddress(destTokenAddress)); - - token.transfer(bytes32ToAddress(destReceiverAddress), amount - commission); - emit RequestProcessed(requestHash); + // from -> to mapping + mapping(bytes32 => bytes32) public supportedPairs; + mapping(bytes32 => Request) public pendingRequests; + mapping(bytes32 => bool) public processedRequests; + mapping(bytes32 => bool) private committee; + mapping(uint256 => uint256) public committeeSize; + mapping(uint256 => uint256) public signatureThreshold; + mapping(bytes32 => uint256) private collectedCommitteeRewards; + mapping(bytes32 => uint256) private paidOutMemberRewards; + + event CrosschainTransferRequest( + uint256 indexed committeeId, + bytes32 indexed destTokenAddress, + uint256 amount, + bytes32 indexed destReceiverAddress, + uint256 requestNonce + ); + + event RequestSigned(bytes32 requestHash, address signer); + + event RequestProcessed(bytes32 requestHash); + + modifier _onlyOwner() { + require(msg.sender == owner, "CallerIsNotOwner"); + _; + } + modifier _onlyCurrentCommitteeMember() { + require(isInCommittee(committeeId, msg.sender), "NotInCommittee"); + _; } - } - - // Request payout of rewards for signing & relaying cross-chain transfers - // - // Can be called by anyone on behalf of the committee member, - // past or present - function payoutRewards ( - uint256 _committeeId, - address member, - bytes32 _token - ) external { - uint256 outstandingRewards = getOutstandingMemberRewards (_committeeId, member, _token); - - if (outstandingRewards > 0) { - IERC20 token = IERC20(bytes32ToAddress(_token)); - token.transfer(member, outstandingRewards); - paidOutMemberRewards [keccak256(abi.encodePacked(_committeeId, member, _token))] += outstandingRewards; + + constructor( + address[] memory _committee, + uint256 _signatureThreshold, + uint256 _commissionPerDixMille, + uint256 _minimumTransferAmountUsd + ) { + require( + _signatureThreshold > 0, + "Signature threshold must be greater than 0" + ); + require( + _committee.length >= _signatureThreshold, + "Not enough guardians specified" + ); + + owner = msg.sender; + commissionPerDixMille = _commissionPerDixMille; + minimumTransferAmountUsd = _minimumTransferAmountUsd; + committeeId = 0; + + for (uint256 i = 0; i < _committee.length; i++) { + committee[ + keccak256(abi.encodePacked(committeeId, _committee[i])) + ] = true; + } + + committeeSize[committeeId] = _committee.length; + signatureThreshold[committeeId] = _signatureThreshold; } - } - - function getCollectedCommitteeRewards ( - uint256 _committeeId, - bytes32 token - ) public view returns (uint256) { - return collectedCommitteeRewards [keccak256(abi.encodePacked(_committeeId, token))]; - } - - function getPaidOutMemberRewards ( - uint256 _committeeId, - address member, - bytes32 token - ) public view returns (uint256) { - return paidOutMemberRewards [keccak256(abi.encodePacked(_committeeId, member, token))]; - } - - function getOutstandingMemberRewards ( - uint256 _committeeId, - address member, - bytes32 token - ) public view returns (uint256) { - return (getCollectedCommitteeRewards (_committeeId, token) / committeeSize [_committeeId]) - getPaidOutMemberRewards (_committeeId, member, token); - } - - // Queries a price oracle and returns the price of an `amount` number of the `of` tokens denominated in the `in_token` - // - // TODO: this is a mocked method pending an implementation - function queryPrice( - uint256 amountOf, - bytes32 ofToken, - bytes32 inToken - ) public view returns(uint256) { - - if (inToken == USDT) { - return amountOf * 2; + + // Invoke this tx to transfer funds to the destination chain. + // Account needs to approve the Membrane contract to spend the `srcTokenAmount` + // of `srcTokenAddress` tokens on their behalf before executing the tx. + // + // Tx emits a CrosschainTransferRequest event that the relayers listen to + // & forward to the destination chain. + function sendRequest( + bytes32 srcTokenAddress, + uint256 amount, + bytes32 destReceiverAddress + ) external { + require( + queryPrice(amount, srcTokenAddress, USDT) > + minimumTransferAmountUsd, + "AmountBelowMinimum" + ); + + address sender = msg.sender; + + IERC20 token = IERC20(bytes32ToAddress(srcTokenAddress)); + + // check if the token is supported + bytes32 destTokenAddress = supportedPairs[srcTokenAddress]; + require(destTokenAddress != 0x0, "Unsupported pair"); + + // lock tokens in this contract + // message sender needs to give approval else this tx will revert + token.transferFrom(sender, address(this), amount); + + emit CrosschainTransferRequest( + committeeId, + destTokenAddress, + amount, + destReceiverAddress, + requestNonce + ); + + requestNonce++; } - if (ofToken == USDT) { - return amountOf / 2; + // aggregates relayer signatures and returns the locked tokens + function receiveRequest( + bytes32 _requestHash, + bytes32 destTokenAddress, + uint256 amount, + bytes32 destReceiverAddress, + uint256 _requestNonce + ) external _onlyCurrentCommitteeMember { + require( + !processedRequests[_requestHash], + "This request has already been processed" + ); + + bytes32 requestHash = keccak256( + abi.encodePacked( + destTokenAddress, + amount, + destReceiverAddress, + _requestNonce + ) + ); + + require(_requestHash == requestHash, "Hash does not match the data"); + + Request storage request = pendingRequests[requestHash]; + require( + !request.signatures[msg.sender], + "This guardian has already signed this request" + ); + + request.signatures[msg.sender] = true; + request.signatureCount++; + + emit RequestSigned(requestHash, msg.sender); + + if (request.signatureCount >= signatureThreshold[committeeId]) { + uint256 commission = (amount * commissionPerDixMille) / DIX_MILLE; + + collectedCommitteeRewards[ + keccak256(abi.encodePacked(committeeId, destTokenAddress)) + ] += commission; + + processedRequests[requestHash] = true; + delete pendingRequests[requestHash]; + + // return the locked tokens + IERC20 token = IERC20(bytes32ToAddress(destTokenAddress)); + + token.transfer( + bytes32ToAddress(destReceiverAddress), + amount - commission + ); + emit RequestProcessed(requestHash); + } } - return amountOf; - } + // Request payout of rewards for signing & relaying cross-chain transfers + // + // Can be called by anyone on behalf of the committee member, + // past or present + function payoutRewards( + uint256 _committeeId, + address member, + bytes32 _token + ) external { + uint256 outstandingRewards = getOutstandingMemberRewards( + _committeeId, + member, + _token + ); + + if (outstandingRewards > 0) { + IERC20 token = IERC20(bytes32ToAddress(_token)); + token.transfer(member, outstandingRewards); + paidOutMemberRewards[ + keccak256(abi.encodePacked(_committeeId, member, _token)) + ] += outstandingRewards; + } + } - function hasSignedRequest( - address guardian, - bytes32 hash - ) external view returns (bool) { - return pendingRequests[hash].signatures[guardian]; - } + function getCollectedCommitteeRewards(uint256 _committeeId, bytes32 token) + public + view + returns (uint256) + { + return + collectedCommitteeRewards[ + keccak256(abi.encodePacked(_committeeId, token)) + ]; + } - function isInCommittee( - uint256 _committeeId, - address account - ) public view returns (bool) { - return committee[keccak256(abi.encodePacked(_committeeId, account))] == true; - } + function getPaidOutMemberRewards( + uint256 _committeeId, + address member, + bytes32 token + ) public view returns (uint256) { + return + paidOutMemberRewards[ + keccak256(abi.encodePacked(_committeeId, member, token)) + ]; + } - function bytes32ToAddress(bytes32 data) internal pure returns (address) { - return address(uint160(uint256(data))); - } + function getOutstandingMemberRewards( + uint256 _committeeId, + address member, + bytes32 token + ) public view returns (uint256) { + return + (getCollectedCommitteeRewards(_committeeId, token) / + committeeSize[_committeeId]) - + getPaidOutMemberRewards(_committeeId, member, token); + } - function addressToBytes32(address addr) internal pure returns (bytes32) { - return bytes32(uint256(uint160(addr))); - } + // Queries a price oracle and returns the price of an `amount` number of the `of` tokens denominated in the `in_token` + // + // TODO: this is a mocked method pending an implementation + function queryPrice( + uint256 amountOf, + bytes32 ofToken, + bytes32 inToken + ) public view returns (uint256) { + if (inToken == USDT) { + return amountOf * 2; + } + + if (ofToken == USDT) { + return amountOf / 2; + } + + return amountOf; + } - function setCommittee(address[] memory _committee, uint256 _signatureThreshold) external _onlyOwner { - require(_signatureThreshold > 0, "Signature threshold must be greater than 0"); - require(_committee.length >= _signatureThreshold, "Not enough guardians specified"); + function hasSignedRequest(address guardian, bytes32 hash) + external + view + returns (bool) + { + return pendingRequests[hash].signatures[guardian]; + } - committeeId += 1; + function isInCommittee(uint256 _committeeId, address account) + public + view + returns (bool) + { + return + committee[keccak256(abi.encodePacked(_committeeId, account))] == + true; + } - for (uint256 i = 0; i < _committee.length; i++) { - committee[keccak256(abi.encodePacked(committeeId, _committee[i]))] = true; + function bytes32ToAddress(bytes32 data) internal pure returns (address) { + return address(uint160(uint256(data))); } - committeeSize [committeeId] = _committee.length; - signatureThreshold [committeeId] = _signatureThreshold; - } + function addressToBytes32(address addr) internal pure returns (bytes32) { + return bytes32(uint256(uint160(addr))); + } - function setOwner(address _owner) external _onlyOwner { - owner = _owner; - } + function setCommittee( + address[] memory _committee, + uint256 _signatureThreshold + ) external _onlyOwner { + require( + _signatureThreshold > 0, + "Signature threshold must be greater than 0" + ); + require( + _committee.length >= _signatureThreshold, + "Not enough guardians specified" + ); + + committeeId += 1; + + for (uint256 i = 0; i < _committee.length; i++) { + committee[ + keccak256(abi.encodePacked(committeeId, _committee[i])) + ] = true; + } + + committeeSize[committeeId] = _committee.length; + signatureThreshold[committeeId] = _signatureThreshold; + } - function addPair(bytes32 from, bytes32 to) external _onlyOwner { - supportedPairs[from] = to; - } + function setOwner(address _owner) external _onlyOwner { + owner = _owner; + } - function removePair(bytes32 from) external _onlyOwner { - delete supportedPairs[from]; - } + function addPair(bytes32 from, bytes32 to) external _onlyOwner { + supportedPairs[from] = to; + } - function setUSDT(bytes32 _USDT) external _onlyOwner { - USDT = _USDT; - } + function removePair(bytes32 from) external _onlyOwner { + delete supportedPairs[from]; + } + function setUSDT(bytes32 _USDT) external _onlyOwner { + USDT = _USDT; + } }