Cross Chain Guard test

This commit is contained in:
Alexey 2021-10-12 18:50:25 +03:00
parent fa7bb9947a
commit c46f3ae1a9
No known key found for this signature in database
GPG Key ID: C77958099D784E76
6 changed files with 65 additions and 24 deletions

View File

@ -1,16 +1,13 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity ^0.7.0; pragma solidity ^0.7.0;
import { IAMB } from "./interfaces/IBridge.sol"; import { CrossChainGuard } from "./bridge/CrossChainGuard.sol";
import "@openzeppelin/contracts/proxy/TransparentUpgradeableProxy.sol"; import "@openzeppelin/contracts/proxy/TransparentUpgradeableProxy.sol";
/** /**
* @dev TransparentUpgradeableProxy where admin acts from a different chain. * @dev TransparentUpgradeableProxy where admin acts from a different chain.
*/ */
contract CrossChainUpgradeableProxy is TransparentUpgradeableProxy { contract CrossChainUpgradeableProxy is TransparentUpgradeableProxy, CrossChainGuard {
IAMB public immutable ambBridge;
bytes32 public immutable adminChainId;
/** /**
* @dev Initializes an upgradeable proxy backed by the implementation at `_logic`. * @dev Initializes an upgradeable proxy backed by the implementation at `_logic`.
*/ */
@ -18,25 +15,23 @@ contract CrossChainUpgradeableProxy is TransparentUpgradeableProxy {
address _logic, address _logic,
address _admin, address _admin,
bytes memory _data, bytes memory _data,
IAMB _ambBridge, address _ambBridge,
uint256 _adminChainId uint256 _adminChainId
) TransparentUpgradeableProxy(_logic, _admin, _data) { ) TransparentUpgradeableProxy(_logic, _admin, _data) CrossChainGuard(_ambBridge, _adminChainId, _admin) {}
ambBridge = _ambBridge;
adminChainId = bytes32(uint256(_adminChainId));
}
/** /**
* @dev Modifier used internally that will delegate the call to the implementation unless the sender is the cross chain admin. * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the cross chain admin.
*/ */
modifier ifAdmin() override { modifier ifAdmin() override {
if ( if (isCalledByOwner()) {
msg.sender == address(ambBridge) &&
ambBridge.messageSourceChainId() == adminChainId &&
ambBridge.messageSender() == _admin()
) {
_; _;
} else { } else {
_fallback(); _fallback();
} }
} }
/**
* @dev Override to allow admin access the fallback function.
*/
function _beforeFallback() internal override {}
} }

View File

@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity ^0.7.0; pragma solidity ^0.7.0;
import { IAMB } from "../CrossChainUpgradeableProxy.sol"; import { IAMB } from "../interfaces/IBridge.sol";
contract MockAMB is IAMB { contract MockAMB is IAMB {
address public xDomainMessageSender; address public xDomainMessageSender;

View File

@ -14,14 +14,14 @@ pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2; pragma experimental ABIEncoderV2;
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import { IERC20Receiver, IERC6777 } from "./interfaces/IBridge.sol"; import { IERC20Receiver, IERC6777, IOmniBridge } from "./interfaces/IBridge.sol";
import { CrossChainGuard } from "./bridge/CrossChainGuard.sol";
import { IVerifier } from "./interfaces/IVerifier.sol"; import { IVerifier } from "./interfaces/IVerifier.sol";
import "./MerkleTreeWithHistory.sol"; import "./MerkleTreeWithHistory.sol";
contract TornadoPool is MerkleTreeWithHistory, IERC20Receiver, ReentrancyGuard { contract TornadoPool is MerkleTreeWithHistory, IERC20Receiver, ReentrancyGuard, CrossChainGuard {
int256 public constant MAX_EXT_AMOUNT = 2**248; int256 public constant MAX_EXT_AMOUNT = 2**248;
uint256 public constant MAX_FEE = 2**248; uint256 public constant MAX_FEE = 2**248;
address public immutable governance;
IVerifier public immutable verifier2; IVerifier public immutable verifier2;
IVerifier public immutable verifier16; IVerifier public immutable verifier16;
@ -63,7 +63,7 @@ contract TornadoPool is MerkleTreeWithHistory, IERC20Receiver, ReentrancyGuard {
event PublicKey(address indexed owner, bytes key); event PublicKey(address indexed owner, bytes key);
modifier onlyGovernance() { modifier onlyGovernance() {
require(msg.sender == governance, "only governance"); require(isCalledByOwner(), "only governance");
_; _;
} }
@ -80,14 +80,17 @@ contract TornadoPool is MerkleTreeWithHistory, IERC20Receiver, ReentrancyGuard {
IERC6777 _token, IERC6777 _token,
address _omniBridge, address _omniBridge,
address _l1Unwrapper, address _l1Unwrapper,
address _governance address _governance,
) MerkleTreeWithHistory(_levels, _hasher) { uint256 _l1ChainId
)
MerkleTreeWithHistory(_levels, _hasher)
CrossChainGuard(address(IOmniBridge(_omniBridge).bridgeContract()), _l1ChainId, _governance)
{
verifier2 = _verifier2; verifier2 = _verifier2;
verifier16 = _verifier16; verifier16 = _verifier16;
token = _token; token = _token;
omniBridge = _omniBridge; omniBridge = _omniBridge;
l1Unwrapper = _l1Unwrapper; l1Unwrapper = _l1Unwrapper;
governance = _governance;
} }
function initialize(uint256 _minimalWithdrawalAmount, uint256 _maximumDepositAmount) external initializer { function initialize(uint256 _minimalWithdrawalAmount, uint256 _maximumDepositAmount) external initializer {

View File

@ -0,0 +1,25 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
import { IAMB } from "../interfaces/IBridge.sol";
contract CrossChainGuard {
IAMB public immutable ambBridge;
bytes32 public immutable ownerChainId;
address public immutable owner;
constructor(
address _ambBridge,
uint256 _ownerChainId,
address _owner
) {
ambBridge = IAMB(_ambBridge);
owner = _owner;
ownerChainId = bytes32(uint256(_ownerChainId));
}
function isCalledByOwner() public virtual returns (bool) {
return
msg.sender == address(ambBridge) && ambBridge.messageSourceChainId() == ownerChainId && ambBridge.messageSender() == owner;
}
}

View File

@ -11,7 +11,7 @@ async function main() {
const omniBridge = '0x59447362798334d3485c64D1e4870Fde2DDC0d75' const omniBridge = '0x59447362798334d3485c64D1e4870Fde2DDC0d75'
const amb = '0x162e898bd0aacb578c8d5f8d6ca588c13d2a383f' const amb = '0x162e898bd0aacb578c8d5f8d6ca588c13d2a383f'
const token = '0xCa8d20f3e0144a72C6B5d576e9Bd3Fd8557E2B04' // WBNB const token = '0xCa8d20f3e0144a72C6B5d576e9Bd3Fd8557E2B04' // WBNB
const l1Unwrapper = '0xcf35E84bbA3506BB97cf6fAEFe6cc1A9bd843Fc2' // WBNB -> BNB const l1Unwrapper = '0x2353Dcda746fa1AAD17C5650Ddf2A20112862197' // WBNB -> BNB
const l1ChainId = 56 const l1ChainId = 56
const Verifier2 = await ethers.getContractFactory('Verifier2') const Verifier2 = await ethers.getContractFactory('Verifier2')
@ -40,6 +40,7 @@ async function main() {
omniBridge, omniBridge,
l1Unwrapper, l1Unwrapper,
govAddress, govAddress,
l1ChainId,
]).slice(1, -1)}\n`, ]).slice(1, -1)}\n`,
) )
const tornadoImpl = prompt('Deploy tornado pool implementation and provide address here:\n') const tornadoImpl = prompt('Deploy tornado pool implementation and provide address here:\n')

View File

@ -47,6 +47,7 @@ describe('TornadoPool', function () {
omniBridge.address, omniBridge.address,
l1Unwrapper.address, l1Unwrapper.address,
gov.address, gov.address,
l1ChainId,
) )
const proxy = await deploy( const proxy = await deploy(
@ -81,6 +82,22 @@ describe('TornadoPool', function () {
"Transaction reverted: function selector was not recognized and there's no fallback function", "Transaction reverted: function selector was not recognized and there's no fallback function",
) )
}) })
it('should configure', async () => {
const { tornadoPool, amb } = await loadFixture(fixture)
const newWithdrawalLimit = utils.parseEther('0.01337')
const newDepositLimit = utils.parseEther('1337')
const { data } = await tornadoPool.populateTransaction.configureLimits(
newWithdrawalLimit,
newDepositLimit,
)
await amb.execute(tornadoPool.address, data)
expect(await tornadoPool.maximumDepositAmount()).to.be.equal(newDepositLimit)
expect(await tornadoPool.minimalWithdrawalAmount()).to.be.equal(newWithdrawalLimit)
})
}) })
it('encrypt -> decrypt should work', () => { it('encrypt -> decrypt should work', () => {