mirror of
https://github.com/tornadocash/tornado-nova
synced 2024-02-02 14:53:56 +01:00
Cross Chain Guard test
This commit is contained in:
parent
fa7bb9947a
commit
c46f3ae1a9
@ -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 {}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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 {
|
||||||
|
25
contracts/bridge/CrossChainGuard.sol
Normal file
25
contracts/bridge/CrossChainGuard.sol
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
@ -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')
|
||||||
|
@ -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', () => {
|
||||||
|
Loading…
Reference in New Issue
Block a user