Add proposal and tests solidity code
This commit is contained in:
parent
8c97665093
commit
51a0b178bf
@ -1,4 +1,4 @@
|
|||||||
# Proposal title
|
# Proposal to compensate relayer attack losses
|
||||||
|
|
||||||
### Changes / effect description
|
### Changes / effect description
|
||||||
|
|
||||||
@ -10,15 +10,14 @@
|
|||||||
|
|
||||||
- Rust ([Need only for Windows](https://doc.rust-lang.org/cargo/getting-started/installation.html))
|
- Rust ([Need only for Windows](https://doc.rust-lang.org/cargo/getting-started/installation.html))
|
||||||
- Foundryup ([Windows](https://github.com/altugbakan/foundryup-windows), [Linux](https://book.getfoundry.sh/getting-started/installation))
|
- Foundryup ([Windows](https://github.com/altugbakan/foundryup-windows), [Linux](https://book.getfoundry.sh/getting-started/installation))
|
||||||
- Node 14 or higher ([Windows](https://github.com/coreybutler/nvm-windows), [Linux](https://github.com/nvm-sh/nvm))
|
- Node 18 or higher ([Windows](https://github.com/coreybutler/nvm-windows), [Linux](https://github.com/nvm-sh/nvm))
|
||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
|
|
||||||
```text
|
```text
|
||||||
git clone --recurse-submodules <proposal-repo-link>
|
git clone --recurse-submodules https://git.tornado.ws/Theo/proposal-33-compensate-relayer-losses
|
||||||
cd <proposal-name>
|
cd proposal-33-compensate-relayer-losses
|
||||||
npm install
|
npm install
|
||||||
npm run init
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Testing
|
### Testing
|
||||||
|
1
lib/forge-std
Submodule
1
lib/forge-std
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit f73c73d2018eb6a111f35e4dae7b4f27401e9421
|
@ -19,6 +19,7 @@
|
|||||||
"@openzeppelin/upgrades-core": "^1.26.2",
|
"@openzeppelin/upgrades-core": "^1.26.2",
|
||||||
"axios": "^1.5.1",
|
"axios": "^1.5.1",
|
||||||
"dotenv": "^16.3.1",
|
"dotenv": "^16.3.1",
|
||||||
|
"env-cmd": "^10.1.0",
|
||||||
"web3": "^4.2.0",
|
"web3": "^4.2.0",
|
||||||
"web3-utils": "^4.0.7"
|
"web3-utils": "^4.0.7"
|
||||||
},
|
},
|
||||||
|
@ -15,11 +15,7 @@ async function fetchFailedWithdrawals() {
|
|||||||
|
|
||||||
let failedWithdrawalTransactions = [];
|
let failedWithdrawalTransactions = [];
|
||||||
for (let blockNumber = attackStartBlock; blockNumber <= attackEndBlock; blockNumber++) {
|
for (let blockNumber = attackStartBlock; blockNumber <= attackEndBlock; blockNumber++) {
|
||||||
let block = null;
|
const block = await web3.eth.getBlock(blockNumber);
|
||||||
while (block == null)
|
|
||||||
try {
|
|
||||||
block = await web3.eth.getBlock(blockNumber);
|
|
||||||
} catch (e) {}
|
|
||||||
const results = await Promise.allSettled(block.transactions.map((tx) => web3.eth.getTransactionReceipt(tx as string)));
|
const results = await Promise.allSettled(block.transactions.map((tx) => web3.eth.getTransactionReceipt(tx as string)));
|
||||||
const transactions = results.filter((r) => r.status === "fulfilled").map((r) => (r as PromiseFulfilledResult<TxReceipt>).value);
|
const transactions = results.filter((r) => r.status === "fulfilled").map((r) => (r as PromiseFulfilledResult<TxReceipt>).value);
|
||||||
failedWithdrawalTransactions.push(...transactions.filter((tx) => tx.to === routerAddress.toLowerCase() && tx.status == 0));
|
failedWithdrawalTransactions.push(...transactions.filter((tx) => tx.to === routerAddress.toLowerCase() && tx.status == 0));
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
pragma solidity ^0.8.19;
|
|
||||||
|
|
||||||
import { IGovernance } from "@interfaces/IGovernance.sol";
|
|
||||||
|
|
||||||
contract ExampleProposal {
|
|
||||||
function executeProposal() public {
|
|
||||||
/* ... */
|
|
||||||
}
|
|
||||||
}
|
|
29
src/RelayerCompensationProposal.sol
Normal file
29
src/RelayerCompensationProposal.sol
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
pragma solidity ^0.8.19;
|
||||||
|
|
||||||
|
import { IGovernance } from "@interfaces/IGovernance.sol";
|
||||||
|
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||||
|
|
||||||
|
contract RelayerCompensationProposal {
|
||||||
|
IERC20 public constant TORN = IERC20(0x77777FeDdddFfC19Ff86DB637967013e6C6A116C);
|
||||||
|
|
||||||
|
struct RelayerLoss {
|
||||||
|
address relayer;
|
||||||
|
uint256 lostAmountInTorn;
|
||||||
|
}
|
||||||
|
|
||||||
|
function executeProposal() public {
|
||||||
|
// Data from 'data/relayerLosses.txt', generated by 'scripts/calculateLosses.ts'
|
||||||
|
RelayerLoss[4] memory relayerLosses = [
|
||||||
|
RelayerLoss(0x864DF9CD806D58341f13602103Bf853066ff962a, 625_894_225_496_155_734_516),
|
||||||
|
RelayerLoss(0x5555555731006f71f121144534Ca7C8799F66AA3, 43_970_301_082_908_267_318),
|
||||||
|
RelayerLoss(0x2Ee39Ff05643bC7cc9ed31B71e142429044A425C, 189_640_345_451_160_934_437),
|
||||||
|
RelayerLoss(0x03392600086874456E08D2bAc104380BCdEBCfC0, 129_757_783_603_193_410_350)
|
||||||
|
];
|
||||||
|
|
||||||
|
for (uint256 i = 0; i < relayerLosses.length; i++) {
|
||||||
|
TORN.transfer(relayerLosses[i].relayer, relayerLosses[i].lostAmountInTorn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,24 +0,0 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
|
||||||
pragma solidity ^0.8.19;
|
|
||||||
|
|
||||||
import { ProposalUtils } from "./utils/ProposalUtils.sol";
|
|
||||||
import { ExampleProposal } from "@root/ExampleProposal.sol";
|
|
||||||
|
|
||||||
import { console2 } from "@forge-std/console2.sol";
|
|
||||||
|
|
||||||
contract TestExampleProposal is ProposalUtils {
|
|
||||||
modifier executeCurrentProposalBefore() {
|
|
||||||
createAndExecuteProposal();
|
|
||||||
_;
|
|
||||||
}
|
|
||||||
|
|
||||||
function createAndExecuteProposal() public {
|
|
||||||
address proposalAddress = address(new ExampleProposal()); /* your proposal initialization */
|
|
||||||
|
|
||||||
proposeAndExecute(proposalAddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* your tests */
|
|
||||||
|
|
||||||
function testProposal() public executeCurrentProposalBefore { }
|
|
||||||
}
|
|
56
test/RelayerCompensationProposal.t.sol
Normal file
56
test/RelayerCompensationProposal.t.sol
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
pragma solidity ^0.8.19;
|
||||||
|
|
||||||
|
import { ProposalUtils } from "./utils/ProposalUtils.sol";
|
||||||
|
import { RelayerCompensationProposal } from "@root/RelayerCompensationProposal.sol";
|
||||||
|
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||||
|
|
||||||
|
import { console2 } from "@forge-std/console2.sol";
|
||||||
|
|
||||||
|
contract TestExampleProposal is ProposalUtils, RelayerCompensationProposal {
|
||||||
|
modifier executeCurrentProposalBefore() {
|
||||||
|
createAndExecuteProposal();
|
||||||
|
_;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createAndExecuteProposal() public {
|
||||||
|
address proposalAddress = address(new RelayerCompensationProposal());
|
||||||
|
|
||||||
|
proposeAndExecute(proposalAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRelayerLosses() internal pure returns (RelayerLoss[4] memory) {
|
||||||
|
return [
|
||||||
|
RelayerLoss(0x864DF9CD806D58341f13602103Bf853066ff962a, 625_894_225_496_155_734_516),
|
||||||
|
RelayerLoss(0x5555555731006f71f121144534Ca7C8799F66AA3, 43_970_301_082_908_267_318),
|
||||||
|
RelayerLoss(0x2Ee39Ff05643bC7cc9ed31B71e142429044A425C, 189_640_345_451_160_934_437),
|
||||||
|
RelayerLoss(0x03392600086874456E08D2bAc104380BCdEBCfC0, 129_757_783_603_193_410_350)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function testRelayerGotCompensation() public {
|
||||||
|
RelayerLoss[4] memory relayerLosses = getRelayerLosses();
|
||||||
|
|
||||||
|
uint256[4] memory balancesBeforeProposal;
|
||||||
|
for (uint256 i = 0; i < relayerLosses.length; i++) {
|
||||||
|
balancesBeforeProposal[i] = TORN.balanceOf(relayerLosses[i].relayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
createAndExecuteProposal();
|
||||||
|
|
||||||
|
for (uint256 i = 0; i < relayerLosses.length; i++) {
|
||||||
|
uint256 updatedBalance = TORN.balanceOf(relayerLosses[i].relayer);
|
||||||
|
require(balancesBeforeProposal[i] + relayerLosses[i].lostAmountInTorn == updatedBalance, "Compensation failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function testLossesDataIsValid() public pure {
|
||||||
|
RelayerLoss[4] memory relayerLosses = getRelayerLosses();
|
||||||
|
uint256 tornDecimals = 1e18;
|
||||||
|
|
||||||
|
require(relayerLosses[0].lostAmountInTorn / tornDecimals == 625);
|
||||||
|
require(relayerLosses[1].lostAmountInTorn / tornDecimals == 43);
|
||||||
|
require(relayerLosses[2].lostAmountInTorn / tornDecimals == 189);
|
||||||
|
require(relayerLosses[3].lostAmountInTorn / tornDecimals == 129);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user