├── .gitignore ├── .gitmodules ├── src ├── IArbitrable.sol ├── test │ ├── Reps.spec.txt │ ├── Hevm.sol │ ├── Reps.t.sol │ ├── CentralizedArbitrator.sol │ └── console.sol ├── IArbitrator.sol └── Reps.sol └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | cache 2 | out -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib/ds-test"] 2 | path = lib/ds-test 3 | url = https://github.com/dapphub/ds-test 4 | [submodule "lib/solmate"] 5 | path = lib/solmate 6 | url = https://github.com/rari-capital/solmate 7 | -------------------------------------------------------------------------------- /src/IArbitrable.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8; 3 | 4 | import "./IArbitrator.sol"; 5 | 6 | /** 7 | * @title IArbitrable 8 | * Arbitrable interface. Note that this interface follows the ERC-792 standard. 9 | * When developing arbitrable contracts, we need to: 10 | * - Define the action taken when a ruling is received by the contract. 11 | * - Allow dispute creation. For this a function must call arbitrator.createDispute{value: _fee}(_choices,_extraData); 12 | */ 13 | interface IArbitrable { 14 | /** 15 | * @dev To be raised when a ruling is given. 16 | * @param _arbitrator The arbitrator giving the ruling. 17 | * @param _disputeID ID of the dispute in the Arbitrator contract. 18 | * @param _ruling The ruling which was given. 19 | */ 20 | event Ruling( 21 | IArbitrator indexed _arbitrator, 22 | uint256 indexed _disputeID, 23 | uint256 _ruling 24 | ); 25 | 26 | /** 27 | * @dev Give a ruling for a dispute. Must be called by the arbitrator. 28 | * The purpose of this function is to ensure that the address calling it has the right to rule on the contract. 29 | * @param _disputeID ID of the dispute in the Arbitrator contract. 30 | * @param _ruling Ruling given by the arbitrator. Note that 0 is reserved for "Not able/wanting to make a decision". 31 | */ 32 | function rule(uint256 _disputeID, uint256 _ruling) external; 33 | } 34 | -------------------------------------------------------------------------------- /src/test/Reps.spec.txt: -------------------------------------------------------------------------------- 1 | /** 2 | * constructor 3 | * - sets name, symbol, and weth address 4 | * 5 | * newRep 6 | * - increments count, stores data, mints to owner, and emits event 7 | * 8 | * setRep 9 | * - rejects if rep doesn't exist 10 | * - rejects if rep owner is msg.sender 11 | * - rejects if already delegated to this rep 12 | * - sets rep, boosts eth for rep, and emits event 13 | * 14 | * clearRep 15 | * - rejects if no rep is set 16 | * - sets rep to 0 and emits event 17 | * 18 | * boostEthFor 19 | * - updates claimable, checkpoint time, stream pool, stream rate 20 | * 21 | * claimableAt 22 | * - shows expected value 23 | * - returns 0 for non-existant reps 24 | * 25 | * claimFor 26 | * - transfers claimableAt ETH to rep owner if they can receive ETH 27 | * - transfers claimableAt WETH to rep owner if they can't receive ETH 28 | * - rejects if rep doesn't exist (i.e. owner is address(0)) 29 | * 30 | * dispute 31 | * - rejects for already disputed rep 32 | * - rejects if fee not supplied 33 | * - creates new dispute in arbitrator, sets dispute id 34 | * 35 | * rule 36 | * - rejects for non-existant dispute 37 | * - rejects if called by non-arbitrator 38 | * - if ruling is 1, 39 | burns rep NFT, 40 | sends all funds to dispute creator, 41 | sets rep stream rate, claimable, pool to 0, 42 | and sets new checkpoint. 43 | * - for all rulings, sets rep to not disputed, emits Ruling 44 | * 45 | */ -------------------------------------------------------------------------------- /src/IArbitrator.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8; 3 | 4 | import "./IArbitrable.sol"; 5 | 6 | /** 7 | * @title Arbitrator 8 | * Arbitrator interface that implements the new arbitration standard. 9 | * Unlike the ERC-792 this standard doesn't have anything related to appeals, so each arbitrator can implement an appeal system that suits it the most. 10 | * When developing arbitrator contracts we need to: 11 | * - Define the functions for dispute creation (createDispute). Don't forget to store the arbitrated contract and the disputeID (which should be unique, may nbDisputes). 12 | * - Define the functions for cost display (arbitrationCost). 13 | * - Allow giving rulings. For this a function must call arbitrable.rule(disputeID, ruling). 14 | */ 15 | interface IArbitrator { 16 | /** 17 | * @dev To be emitted when a dispute is created. 18 | * @param _disputeID ID of the dispute. 19 | * @param _arbitrable The contract which created the dispute. 20 | */ 21 | event DisputeCreation( 22 | uint256 indexed _disputeID, 23 | IArbitrable indexed _arbitrable 24 | ); 25 | 26 | /** 27 | * @dev Create a dispute. Must be called by the arbitrable contract. 28 | * Must pay at least arbitrationCost(_extraData). 29 | * @param _choices Amount of choices the arbitrator can make in this dispute. 30 | * @param _extraData Can be used to give additional info on the dispute to be created. 31 | * @return disputeID ID of the dispute created. 32 | */ 33 | function createDispute(uint256 _choices, bytes calldata _extraData) 34 | external 35 | payable 36 | returns (uint256 disputeID); 37 | 38 | /** 39 | * @dev Compute the cost of arbitration. It is recommended not to increase it often, as it can be highly time and gas consuming for the arbitrated contracts to cope with fee augmentation. 40 | * @param _extraData Can be used to give additional info on the dispute to be created. 41 | * @return cost Required cost of arbitration. 42 | */ 43 | function arbitrationCost(bytes calldata _extraData) 44 | external 45 | view 46 | returns (uint256 cost); 47 | } 48 | -------------------------------------------------------------------------------- /src/test/Hevm.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Unlicense 2 | pragma solidity 0.8.10; 3 | 4 | interface Hevm { 5 | // Set block.timestamp (newTimestamp) 6 | function warp(uint256) external; 7 | 8 | // Set block.height (newHeight) 9 | function roll(uint256) external; 10 | 11 | // Set block.basefee (newBasefee) 12 | function fee(uint256) external; 13 | 14 | // Loads a storage slot from an address (who, slot) 15 | function load(address, bytes32) external returns (bytes32); 16 | 17 | // Stores a value to an address' storage slot, (who, slot, value) 18 | function store( 19 | address, 20 | bytes32, 21 | bytes32 22 | ) external; 23 | 24 | // Signs data, (privateKey, digest) => (v, r, s) 25 | function sign(uint256, bytes32) 26 | external 27 | returns ( 28 | uint8, 29 | bytes32, 30 | bytes32 31 | ); 32 | 33 | // Gets address for a given private key, (privateKey) => (address) 34 | function addr(uint256) external returns (address); 35 | 36 | // Performs a foreign function call via terminal, (stringInputs) => (result) 37 | function ffi(string[] calldata) external returns (bytes memory); 38 | 39 | // Sets the *next* call's msg.sender to be the input address 40 | function prank(address) external; 41 | 42 | // Sets all subsequent calls' msg.sender to be the input address until `stopPrank` is called 43 | function startPrank(address) external; 44 | 45 | // Sets the *next* call's msg.sender to be the input address, and the tx.origin to be the second input 46 | function prank(address, address) external; 47 | 48 | // Sets all subsequent calls' msg.sender to be the input address until `stopPrank` is called, and the tx.origin to be the second input 49 | function startPrank(address, address) external; 50 | 51 | // Resets subsequent calls' msg.sender to be `address(this)` 52 | function stopPrank() external; 53 | 54 | // Sets an address' balance, (who, newBalance) 55 | function deal(address, uint256) external; 56 | 57 | // Sets an address' code, (who, newCode) 58 | function etch(address, bytes calldata) external; 59 | 60 | // Expects an error on next call 61 | function expectRevert(bytes calldata) external; 62 | 63 | function expectRevert(bytes4) external; 64 | 65 | // Record all storage reads and writes 66 | function record() external; 67 | 68 | // Gets all accessed reads and write slot from a recording session, for a given address 69 | function accesses(address) 70 | external 71 | returns (bytes32[] memory reads, bytes32[] memory writes); 72 | 73 | // Prepare an expected log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData). 74 | // Call this function, then emit an event, then call a function. Internally after the call, we check if 75 | // logs were emitted in the expected order with the expected topics and data (as specified by the booleans) 76 | function expectEmit( 77 | bool, 78 | bool, 79 | bool, 80 | bool 81 | ) external; 82 | 83 | // Mocks a call to an address, returning specified data. 84 | // Calldata can either be strict or a partial match, e.g. if you only 85 | // pass a Solidity selector to the expected calldata, then the entire Solidity 86 | // function will be mocked. 87 | function mockCall( 88 | address, 89 | bytes calldata, 90 | bytes calldata 91 | ) external; 92 | 93 | // Clears all mocked calls 94 | function clearMockedCalls() external; 95 | 96 | // Expect a call to an address with the specified calldata. 97 | // Calldata can either be strict or a partial match 98 | function expectCall(address, bytes calldata) external; 99 | 100 | function getCode(string calldata) external returns (bytes memory); 101 | } 102 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # "Reps" (working title) 2 | Governance delegation protocol 3 | 4 | ## Purpose 5 | ### General problems 6 | **Community members cannot keep track of all their delegates over many DAOs and many decisions**, so participation will continue to be poor or delegates will have little incentive to represent their constituents. 7 | 8 | **People are not checking up on what their delegates are doing. And even if they do check up on them, the only thing delegates stand to lose is one person's voting power.** 9 | 10 | **Delegates are not being paid to push governance forward, and are more like hobbyists**. Hobbyist representatives might represent us well, but they probably aren't as active as we'd like in pushing DAOs towards their goals. Paid delegates whose pay depends on them doing a good job might do better. 11 | 12 | ## Proposal 13 | Create a protocol that: 14 | - Supports multi-community delegates (delegates can themselves be communities, i.e. political parties), allowing people to browse delegates for all their communities in the same place and delegate more than one token at once, to reduce the number of actions they need to take 15 | - Lets delegates get paid to do governance work 16 | - As trustlessly as possible, **keeps delegates accountable to their constituents by giving them more to lose if they break their promises**, without putting the burden on constituents to put lots of time into oversight 17 | 18 | ## User stories 19 | DAO member: 20 | - As a member of many DAOs, I want to view all my currently undelegated voting power 21 | - As a member of many DAOs, I want to quickly find delegates who can represent me well in all my communities 22 | - As a member of many DAOs, I want to quickly delegate my voting power to those delegates 23 | 24 | Delegate: 25 | - As a delegate, I want to present a promise about how I will act when governing 26 | - As a delegate, I want to get paid for fulfilling my promise 27 | 28 | Challenger: 29 | - As a challenger, I want to get paid for finding delegates breaking their promises 30 | 31 | ## Specs 32 | `Reps` contract: 33 | - mints new `Rep` NFTs. Each Rep NFT contains a promiseURI and hash. 34 | - uses the Gnosis / Snapshot pattern for delegation, in which delegations are simple data strutctures including a delegator, an id, and a delegatee. This protocol is intended to be used with Snapshot or other off-chain voting solutions. 35 | - boosts ETH for a Rep -- add more ETH to the payment pool / challenge bounty for a Rep's owner. 36 | - challenges a Rep -- pay a fee to challenge a Rep, activating a dispute resolution system to determine if a Rep is upholding their `promise`. 37 | - "fires" a Rep -- if a challenge succeeds and a Rep is found to have broken their promise, the Rep NFT is burned, and any remaining Eth in that Rep's pool goes to the successful challenger. People delegated to that Rep will need to switch their delegation to reactivate it. 38 | 39 | ### How voting power might get calced 40 | 41 | This protocol is intended to be used with Snapshot (snapshot.org), though it could probably be used by other systems, too. So voting power would be calculated similarly to how current Snapshot delegation works. 42 | 43 | - A delegation is just a delegator id (the msg.sender), a delegatee id (in this case, the NFT id instead of an address), and an arbitrary id (bytes32). 44 | - This should be used to calculate voting power the same way as the Gnosis contract that is currently used by Snapshot, I assume something like [this](https://github.com/snapshot-labs/snapshot-strategies/blob/master/src/strategies/delegation/index.ts) 45 | - The only difference being you are delegating to the current owner of that Rep NFT instead of to an address directly. 46 | 47 | ### TODOs 48 | - [X] Decide on dispute resolution system (Kleros' interfaces) 49 | - [ ] Talk to Snapshot about integration 50 | - [X] Testing 51 | - [ ] Dapp -- frontend, subgraph, etc. 52 | 53 | # Development 54 | - install [Foundry](https://github.com/gakonst/foundry) 55 | - `forge update` to install libs 56 | - `forge build` to compile 57 | -------------------------------------------------------------------------------- /src/Reps.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Unlicense 2 | // Includes code modified from Gnosis https://github.com/gnosis/delegate-registry.git 3 | pragma solidity 0.8.10; 4 | 5 | import {ERC721} from "solmate/tokens/ERC721.sol"; 6 | import {ReentrancyGuard} from "solmate/utils/ReentrancyGuard.sol"; 7 | import {IArbitrable} from "./IArbitrable.sol"; 8 | import {IArbitrator} from "./IArbitrator.sol"; 9 | 10 | interface IWETH { 11 | function transfer(address, uint256) external; 12 | 13 | function deposit() external payable; 14 | } 15 | 16 | contract Reps is ERC721, ReentrancyGuard, IArbitrable { 17 | //===== Structs =====// 18 | 19 | struct Dispute { 20 | uint256 id; 21 | address creator; 22 | } 23 | 24 | //===== State =====// 25 | // The first key is the delegator and the second key an id. 26 | // The value is the id of the Rep NFT. 27 | mapping(address => mapping(bytes32 => uint256)) public delegation; 28 | 29 | uint256 public repCount; 30 | mapping(uint256 => string) private _promiseURIs; 31 | mapping(uint256 => bytes32) private _promiseHashes; 32 | mapping(uint256 => uint256) private _checkpointTimes; 33 | mapping(uint256 => uint256) private _claimable; 34 | mapping(uint256 => uint256) private _streamPools; 35 | mapping(uint256 => uint256) private _streamRates; 36 | mapping(uint256 => address) private _arbitrators; 37 | mapping(uint256 => Dispute) private _repDisputes; 38 | mapping(uint256 => uint256) private _disputeReps; 39 | 40 | address public immutable weth; 41 | 42 | //===== Events =====// 43 | 44 | event TransferETH(address to, uint256 value, bool success); 45 | 46 | event Checkpoint(uint256 rep, uint256 claimable, uint256 streaming); 47 | 48 | // Using these events it is possible to process the events to build up reverse lookups. 49 | // The indeces allow it to be very partial about how to build this lookup (e.g. only for a specific rep). 50 | event SetRep( 51 | address indexed delegator, 52 | bytes32 indexed id, 53 | uint256 indexed rep 54 | ); 55 | event ClearRep( 56 | address indexed delegator, 57 | bytes32 indexed id, 58 | uint256 indexed rep 59 | ); 60 | 61 | //===== Constructor =====// 62 | 63 | constructor( 64 | string memory name, 65 | string memory symbol, 66 | address weth_ 67 | ) ERC721(name, symbol) { 68 | weth = weth_; 69 | } 70 | 71 | //===== External Functions =====// 72 | 73 | /** 74 | @notice Creates a new Rep NFT. 75 | 76 | @param owner The initial owner of the Rep NFT 77 | @param promiseURI Universal resource identifier for the Rep's promise text 78 | @param promiseHash_ A keccak256 hash of the content stored in/at the promise URI 79 | @param arbitrator Arbitrator that will handle challenges for this rep 80 | */ 81 | function newRep( 82 | address owner, 83 | string memory promiseURI, 84 | bytes32 promiseHash_, 85 | address arbitrator 86 | ) external returns (uint256) { 87 | repCount += 1; 88 | _promiseURIs[repCount] = promiseURI; 89 | _promiseHashes[repCount] = promiseHash_; 90 | _arbitrators[repCount] = arbitrator; 91 | _mint(owner, repCount); 92 | return repCount; 93 | } 94 | 95 | /** 96 | @notice Sets a rep for the msg.sender and a specific id. 97 | The combination of msg.sender and the id can be seen as a unique key. 98 | 99 | @param id Id for which the delegate should be set 100 | @param rep Id of the Rep NFT 101 | */ 102 | function setRep(bytes32 id, uint256 rep) external payable repExists(rep) { 103 | require(ownerOf[rep] != msg.sender, "Can't delegate to self"); 104 | uint256 currentRep = delegation[msg.sender][id]; 105 | require(rep != currentRep, "Already delegated to this rep"); 106 | 107 | // Update delegation mapping 108 | delegation[msg.sender][id] = rep; 109 | if (msg.value > 0) boostEthFor(rep); 110 | 111 | if (currentRep != 0) { 112 | emit ClearRep(msg.sender, id, currentRep); 113 | } 114 | 115 | emit SetRep(msg.sender, id, rep); 116 | } 117 | 118 | /** 119 | @notice Clears a rep for the msg.sender and a specific id. 120 | The combination of msg.sender and the id can be seen as a unique key. 121 | 122 | @param id Id for which the rep should be set 123 | */ 124 | function clearRep(bytes32 id) external { 125 | uint256 currentRep = delegation[msg.sender][id]; 126 | require(currentRep != 0, "No rep set"); 127 | 128 | // update delegation mapping 129 | delegation[msg.sender][id] = 0; 130 | 131 | emit ClearRep(msg.sender, id, currentRep); 132 | } 133 | 134 | /** 135 | @notice Claim ETH or WETH for the current owner of a Rep NFT 136 | 137 | @dev Claiming for a rep with owner address(0) will send to address(0), 138 | but there's no way to get that eth back anyway, so no harm done. 139 | */ 140 | function claimFor(uint256 rep) external repExists(rep) { 141 | _newCheckpoint(rep); 142 | address claimee = ownerOf[rep]; 143 | uint256 value = _claimable[rep]; 144 | _claimable[rep] = 0; 145 | _transferETHOrWETH(claimee, value); 146 | } 147 | 148 | /** 149 | @notice Accuse the owner of a Rep NFT of breaking their promise by creating a dispute in 150 | that rep's arbitrator contract. 151 | */ 152 | function dispute(uint256 rep) external payable returns (uint256 id) { 153 | require(_repDisputes[rep].creator == address(0), "Already disputed"); 154 | address arbitrator = _arbitrators[rep]; 155 | id = IArbitrator(arbitrator).createDispute{value: msg.value}(2, ""); 156 | _repDisputes[rep] = Dispute(id, msg.sender); 157 | _disputeReps[id] = rep; 158 | } 159 | 160 | /** 161 | @notice Resolve a dispute. 162 | If ruling is 1, burns the Rep NFT and sends remaining payment to the challenger. 163 | 164 | @dev Callable only by a Rep NFT's arbitrator in accordance with the Arbitrator/Arbitrable interfaces. 165 | 166 | @dev No need to reset state around stream pools, disputes, and so on if ruling is 1: burning the NFT is enough. 167 | 168 | @param ruling 0 -- refused to arbitrate, 1 -- fired, 2 -- not fired 169 | */ 170 | function rule(uint256 disputeId, uint256 ruling) external { 171 | uint256 rep = _disputeReps[disputeId]; 172 | require(rep != 0, "Non-existant rep"); 173 | address arbitrator = _arbitrators[rep]; 174 | require(arbitrator == msg.sender, "Arbitrator only"); 175 | if (ruling == 1) { 176 | // you're fired 177 | _burn(rep); 178 | // send remaining rep funds to dispute creator 179 | uint256 amount = _claimable[rep] + _streamPools[rep]; 180 | address creator = _repDisputes[rep].creator; 181 | _transferETHOrWETH(creator, amount); 182 | } else { 183 | // rep is no longer disputed 184 | delete _repDisputes[rep]; 185 | } 186 | emit Ruling(IArbitrator(arbitrator), disputeId, ruling); 187 | } 188 | 189 | function promiseHash(uint256 rep) 190 | external 191 | view 192 | repExists(rep) 193 | returns (bytes32) 194 | { 195 | return _promiseHashes[rep]; 196 | } 197 | 198 | function repPaymentData(uint256 rep) 199 | external 200 | view 201 | repExists(rep) 202 | returns ( 203 | uint256, 204 | uint256, 205 | uint256, 206 | uint256 207 | ) 208 | { 209 | return ( 210 | _checkpointTimes[rep], 211 | _claimable[rep], 212 | _streamPools[rep], 213 | _streamRates[rep] 214 | ); 215 | } 216 | 217 | function repDisputeData(uint256 rep) 218 | external 219 | view 220 | repExists(rep) 221 | returns ( 222 | address, 223 | uint256, 224 | address 225 | ) 226 | { 227 | return ( 228 | _arbitrators[rep], 229 | _repDisputes[rep].id, 230 | _repDisputes[rep].creator 231 | ); 232 | } 233 | 234 | //===== Public Functions =====// 235 | 236 | function tokenURI(uint256 rep) 237 | public 238 | view 239 | override 240 | repExists(rep) 241 | returns (string memory) 242 | { 243 | return _promiseURIs[rep]; 244 | } 245 | 246 | /** 247 | @notice Add additional ETH to the payment / bounty pool for a Rep. 248 | 249 | @dev If the rep's owner is address(0), eth paid here is lost! 250 | This may be a bad design choice, but it may not be, and it is simple. 251 | */ 252 | function boostEthFor(uint256 rep) public payable { 253 | _newCheckpoint(rep); 254 | _streamRates[rep] = _streamPools[rep]; 255 | } 256 | 257 | /** 258 | @notice Predict claimable ETH for a Rep NFT owner at a given time 259 | 260 | @dev Stream rate is such that 100% would be claimable after 365 solidity days, 261 | if nothing is added to the pool. Adding to the pool increases the rate. 262 | */ 263 | function claimableAt(uint256 rep, uint256 timestamp) 264 | public 265 | view 266 | returns (uint256) 267 | { 268 | if (timestamp < _checkpointTimes[rep]) return 0; 269 | uint256 timePassed = timestamp - _checkpointTimes[rep]; 270 | uint256 claimable = (_streamRates[rep] * timePassed) / 365 days; 271 | if (claimable > _streamPools[rep]) { 272 | return _streamPools[rep]; 273 | } 274 | return claimable; 275 | } 276 | 277 | //===== Private Functions =====// 278 | 279 | function _newCheckpoint(uint256 rep) private { 280 | uint256 timePassed = block.timestamp - _checkpointTimes[rep]; 281 | uint256 newClaimable = (_streamRates[rep] * timePassed) / 365 days; 282 | if (newClaimable > _streamPools[rep] + msg.value) 283 | newClaimable = _streamPools[rep] + msg.value; 284 | _checkpointTimes[rep] = block.timestamp; 285 | _claimable[rep] = _claimable[rep] + newClaimable; 286 | _streamPools[rep] = _streamPools[rep] + msg.value - newClaimable; 287 | emit Checkpoint(rep, _claimable[rep], _streamPools[rep]); 288 | } 289 | 290 | function _transferETHOrWETH(address to, uint256 value) 291 | private 292 | nonReentrant 293 | returns (bool) 294 | { 295 | // try to transfer ETH with some gas 296 | (bool success, ) = to.call{value: value, gas: 30000}(""); 297 | // if it fails, transfer wrapped ETH 298 | if (!success) { 299 | IWETH(weth).deposit{value: value}(); 300 | IWETH(weth).transfer(to, value); 301 | } 302 | emit TransferETH(to, value, success); 303 | return success; 304 | } 305 | 306 | //===== Modifiers =====// 307 | 308 | modifier repExists(uint256 rep) { 309 | require(ownerOf[rep] != address(0), "Non-existant rep"); 310 | _; 311 | } 312 | } 313 | -------------------------------------------------------------------------------- /src/test/Reps.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Unlicense 2 | pragma solidity 0.8.10; 3 | 4 | import {DSTestPlus} from "solmate/test/utils/DSTestPlus.sol"; 5 | import {ERC20User} from "solmate/test/utils/users/ERC20User.sol"; 6 | import {WETH} from "solmate/tokens/WETH.sol"; 7 | import {CentralizedArbitrator} from "./CentralizedArbitrator.sol"; 8 | import {IArbitrable} from "../IArbitrable.sol"; 9 | import {IArbitrator} from "../IArbitrator.sol"; 10 | import {Reps} from "../Reps.sol"; 11 | import {Hevm} from "./Hevm.sol"; 12 | import "./console.sol"; 13 | 14 | contract RepsTest is DSTestPlus { 15 | event Transfer( 16 | address indexed from, 17 | address indexed to, 18 | uint256 indexed id 19 | ); 20 | 21 | event TransferETH(address to, uint256 value, bool success); 22 | 23 | event Checkpoint(uint256 rep, uint256 claimable, uint256 streaming); 24 | 25 | event SetRep( 26 | address indexed delegator, 27 | bytes32 indexed id, 28 | uint256 indexed rep 29 | ); 30 | 31 | event ClearRep( 32 | address indexed delegator, 33 | bytes32 indexed id, 34 | uint256 indexed rep 35 | ); 36 | 37 | event DisputeCreation( 38 | uint256 indexed _disputeID, 39 | IArbitrable indexed _arbitrable 40 | ); 41 | 42 | event Ruling( 43 | IArbitrator indexed _arbitrator, 44 | uint256 indexed _disputeID, 45 | uint256 _ruling 46 | ); 47 | 48 | Hevm vm = Hevm(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D); 49 | Reps reps; 50 | WETH weth; 51 | CentralizedArbitrator arb; 52 | string name = "Test"; 53 | string symbol = "TST"; 54 | string uri = "uri"; 55 | bytes32 hash_ = keccak256("I promise to be good"); 56 | address alice = address(0xBEEF); 57 | address bob = address(0xFEEB); 58 | 59 | function setUp() public { 60 | weth = new WETH(); 61 | 62 | reps = new Reps(name, symbol, address(weth)); 63 | assertEq(reps.name(), name, "name"); 64 | assertEq(reps.symbol(), symbol, "symbol"); 65 | assertEq(reps.weth(), address(weth), "weth"); 66 | 67 | arb = new CentralizedArbitrator(1000000, 10000, 2000000); 68 | } 69 | 70 | function checkPaymentData( 71 | uint256 rep, 72 | uint256 checkpoint_, 73 | uint256 claimable_, 74 | uint256 pool_, 75 | uint256 rate_ 76 | ) public { 77 | ( 78 | uint256 checkpoint, 79 | uint256 claimable, 80 | uint256 pool, 81 | uint256 rate 82 | ) = reps.repPaymentData(rep); 83 | assertEq(checkpoint, checkpoint_, "checkpoint"); 84 | assertEq(claimable, claimable_, "claimable"); 85 | assertEq(pool, pool_, "pool"); 86 | assertEq(rate, rate_, "rate"); 87 | } 88 | 89 | function checkDisputeData( 90 | uint256 rep, 91 | uint256 disputeId_, 92 | address disputeCreator_ 93 | ) public { 94 | (address arbitrator, uint256 disputeId, address disputeCreator) = reps 95 | .repDisputeData(rep); 96 | assertEq(arbitrator, address(arb), "arbitrator"); 97 | assertEq(disputeId, disputeId_, "disputeId"); 98 | assertEq(disputeCreator, disputeCreator_, "disputeCreator"); 99 | } 100 | 101 | //===== newRep =====// 102 | 103 | function testNewRep(address owner_) public returns (uint256 rep) { 104 | uint256 count = reps.repCount(); 105 | vm.expectEmit(true, true, true, false); 106 | emit Transfer(address(0), owner_, count + 1); 107 | rep = reps.newRep(owner_, uri, hash_, address(arb)); 108 | assertEq(reps.repCount(), count + 1, "count"); 109 | assertEq(reps.ownerOf(rep), owner_, "owner"); 110 | assertEq(reps.tokenURI(rep), uri, "uri"); 111 | assertEq(reps.promiseHash(rep), hash_, "hash"); 112 | 113 | checkPaymentData(rep, 0, 0, 0, 0); 114 | checkDisputeData(rep, 0, address(0)); 115 | } 116 | 117 | //===== setRep =====// 118 | 119 | function testSetRep(uint64 payment) 120 | public 121 | returns (uint256 rep, bytes32 delegationId) 122 | { 123 | // set up rep 124 | rep = testNewRep(alice); 125 | delegationId = keccak256("gov id"); 126 | 127 | // delegate to rep 128 | vm.expectEmit(true, true, true, false); 129 | emit SetRep(address(this), delegationId, rep); 130 | reps.setRep{value: payment}(delegationId, rep); 131 | assertEq(reps.delegation(address(this), delegationId), rep, "rep"); 132 | 133 | checkPaymentData(rep, 0, 0, payment, payment); 134 | } 135 | 136 | function testSetRep_fromRep(uint64 payment1, uint64 payment2) public { 137 | // set up rep with delegation 138 | (uint256 rep, bytes32 delegationId) = testSetRep(payment1); 139 | uint256 rep2 = testNewRep(bob); 140 | delegationId = keccak256("gov id"); 141 | 142 | // set to new rep from old rep 143 | vm.expectEmit(true, true, true, false); 144 | emit SetRep(address(this), delegationId, rep2); 145 | reps.setRep{value: payment2}(delegationId, rep2); 146 | assertEq(reps.delegation(address(this), delegationId), rep2, "rep2"); 147 | 148 | checkPaymentData(rep2, 0, 0, payment2, payment2); 149 | } 150 | 151 | function testFailSetRep_NoRep(uint64 payment) public { 152 | bytes32 delegationId = keccak256("gov id"); 153 | reps.setRep{value: payment}(delegationId, 1); 154 | } 155 | 156 | function testFailSetRep_RepOwnerIsSender(uint64 payment) public { 157 | uint256 rep = testNewRep(address(this)); 158 | bytes32 delegationId = keccak256("gov id"); 159 | reps.setRep{value: payment}(delegationId, rep); 160 | } 161 | 162 | function testFailSetRep_AlreadySet(uint64 payment) public { 163 | (uint256 rep, bytes32 delegationId) = testSetRep(payment); 164 | reps.setRep{value: payment}(delegationId, rep); 165 | } 166 | 167 | //===== clearRep =====// 168 | 169 | function testClearRep() public { 170 | // set up rep 171 | (uint256 rep, bytes32 delegationId) = testSetRep(1 ether); 172 | 173 | // clear rep 174 | vm.expectEmit(true, true, true, false); 175 | emit ClearRep(address(this), delegationId, rep); 176 | reps.clearRep(delegationId); 177 | assertEq( 178 | reps.delegation(address(this), delegationId), 179 | 0, 180 | "cleared rep" 181 | ); 182 | } 183 | 184 | function testFailClearRep_NoRep() public { 185 | bytes32 delegationId = keccak256("gov id"); 186 | reps.clearRep(delegationId); 187 | } 188 | 189 | //===== boostEthFor =====// 190 | 191 | function testBoostEthFor(uint64 payment, uint64 time) 192 | public 193 | returns (uint256 rep) 194 | { 195 | // set up rep 196 | rep = testNewRep(alice); 197 | ( 198 | uint256 checkpoint, 199 | uint256 claimable, 200 | uint256 pool, 201 | uint256 rate 202 | ) = reps.repPaymentData(rep); 203 | 204 | // fast forward 205 | uint256 newTime = checkpoint + time; 206 | uint256 newClaimable = reps.claimableAt(rep, newTime); 207 | vm.warp(newTime); 208 | 209 | // boost 210 | uint256 newPool = pool + payment; 211 | vm.expectEmit(false, false, false, true); 212 | emit Checkpoint(rep, newClaimable, newPool); 213 | reps.boostEthFor{value: payment}(rep); 214 | checkPaymentData(rep, newTime, newClaimable, newPool, rate + payment); 215 | } 216 | 217 | //===== claimableAt =====// 218 | 219 | function testClaimableAt(uint256 time) public { 220 | uint256 rep = testNewRep(alice); 221 | (uint256 checkpoint, , uint256 pool, uint256 rate) = reps 222 | .repPaymentData(rep); 223 | uint256 newTime = checkpoint + time; 224 | uint256 claimable = reps.claimableAt(rep, newTime); 225 | assertEq(claimable, (rate * time) / 365 days, "claimable"); 226 | } 227 | 228 | function testClaimableAt_NonexistentRep(uint256 time) public { 229 | uint256 newTime = block.timestamp + time; 230 | uint256 claimable = reps.claimableAt(1, newTime); 231 | assertEq(claimable, 0, "claimable"); 232 | } 233 | 234 | //===== claimFor =====// 235 | 236 | function testClaimFor( 237 | uint64 payment, 238 | uint64 time1, 239 | uint64 time2 240 | ) public { 241 | // set up rep with payment 242 | uint256 rep = testBoostEthFor(payment, time1); 243 | uint256 repsBalanceBefore = address(reps).balance; 244 | address owner = reps.ownerOf(rep); 245 | uint256 balanceBefore = owner.balance; 246 | 247 | // fast forward 248 | vm.warp(block.timestamp + time2); 249 | uint256 claimable = reps.claimableAt(rep, block.timestamp); 250 | 251 | // claim 252 | vm.expectEmit(false, false, false, true); 253 | emit TransferETH(owner, claimable, true); 254 | reps.claimFor(rep); 255 | assertEq( 256 | repsBalanceBefore - claimable, 257 | address(reps).balance, 258 | "reps balance" 259 | ); 260 | assertEq(balanceBefore + claimable, owner.balance, "owner balance"); 261 | } 262 | 263 | function testClaimFor_WETH( 264 | uint64 payment, 265 | uint64 time1, 266 | uint64 time2 267 | ) public { 268 | // set up rep with payment 269 | uint256 rep = testBoostEthFor(payment, time1); 270 | uint256 repsBalanceBefore = address(reps).balance; 271 | uint256 vmWethBefore = weth.balanceOf(address(vm)); 272 | uint256 vmBalanceBefore = address(vm).balance; 273 | 274 | // fast forward 275 | vm.warp(block.timestamp + time2); 276 | uint256 claimable = reps.claimableAt(rep, block.timestamp); 277 | 278 | // transfer Rep NFT to new owner that can't receive ETH 279 | vm.prank(alice); 280 | vm.expectEmit(true, true, true, false); 281 | emit Transfer(alice, address(vm), rep); 282 | reps.transferFrom(alice, address(vm), rep); 283 | 284 | // claim for new owner, who should receive WETH instead of ETH 285 | vm.expectEmit(false, false, false, true); 286 | emit TransferETH(address(vm), claimable, false); 287 | reps.claimFor(rep); 288 | 289 | assertEq( 290 | repsBalanceBefore - claimable, 291 | address(reps).balance, 292 | "reps balance" 293 | ); 294 | assertEq(vmBalanceBefore, address(vm).balance, "new owner ETH balance"); 295 | assertEq( 296 | vmWethBefore + claimable, 297 | weth.balanceOf(address(vm)), 298 | "new owner WETH balance" 299 | ); 300 | } 301 | 302 | function testFailClaimFor_NonexistentRep() public { 303 | reps.claimFor(1); 304 | } 305 | 306 | //===== dispute =====// 307 | 308 | function testDispute() public returns (uint256 dispute) { 309 | uint256 rep = testNewRep(alice); 310 | uint256 fee = arb.arbitrationCost(""); 311 | vm.expectEmit(true, true, false, false); 312 | emit DisputeCreation(0, reps); 313 | dispute = reps.dispute{value: fee}(rep); 314 | checkDisputeData(rep, 0, address(this)); 315 | } 316 | 317 | function testFailDispute_AlreadyDisputed() public { 318 | uint256 rep = testNewRep(alice); 319 | uint256 fee = arb.arbitrationCost(""); 320 | vm.expectEmit(true, true, false, false); 321 | emit DisputeCreation(0, reps); 322 | reps.dispute{value: fee}(rep); 323 | checkDisputeData(rep, 0, address(this)); 324 | reps.dispute{value: fee}(rep); 325 | } 326 | 327 | function testFailDispute_InvalidValue() public { 328 | uint256 rep = testNewRep(alice); 329 | uint256 fee = arb.arbitrationCost(""); 330 | uint256 dispute = reps.dispute{value: fee - 1}(rep); 331 | } 332 | 333 | //===== rule =====// 334 | 335 | function testRule_Ruling0(uint64 payment) public { 336 | // set up and pay Rep 337 | (uint256 rep, bytes32 delegationId) = testSetRep(payment); 338 | address owner = reps.ownerOf(rep); 339 | uint256 fee = arb.arbitrationCost(""); 340 | 341 | // create dispute 342 | bob.call{value: 1 ether}(""); 343 | vm.expectEmit(true, true, false, false); 344 | emit DisputeCreation(0, reps); 345 | vm.prank(bob); 346 | uint256 dispute = reps.dispute{value: fee}(rep); 347 | checkDisputeData(rep, dispute, bob); 348 | 349 | // rule dispute 350 | uint256 bobBalance = bob.balance; 351 | uint256 ruling = 0; 352 | vm.expectEmit(true, true, false, true); 353 | emit Ruling(arb, dispute, ruling); 354 | vm.prank(address(arb)); 355 | reps.rule(dispute, ruling); 356 | 357 | // ruling 0 consequences: reset dispute, no other change 358 | assertEq(bobBalance, bob.balance, "bob balance"); 359 | assertEq(reps.ownerOf(rep), owner, "rep owner"); 360 | checkPaymentData(rep, block.timestamp, 0, payment, payment); 361 | checkDisputeData(rep, 0, address(0)); 362 | } 363 | 364 | function testRule_Ruling1( 365 | uint64 payment1, 366 | uint64 payment2, 367 | uint64 time 368 | ) public { 369 | // set up and pay Rep 370 | (uint256 rep, bytes32 delegationId) = testSetRep(payment1); 371 | uint256 fee = arb.arbitrationCost(""); 372 | // warp and pay again so claimable[rep] has an interesting value 373 | vm.warp(block.timestamp + time); 374 | reps.boostEthFor{value: payment2}(rep); 375 | 376 | // create dispute 377 | bob.call{value: 1 ether}(""); 378 | vm.expectEmit(true, true, false, false); 379 | emit DisputeCreation(0, reps); 380 | vm.prank(bob); 381 | uint256 dispute = reps.dispute{value: fee}(rep); 382 | checkDisputeData(rep, dispute, bob); 383 | 384 | // rule dispute 385 | uint256 bobBalance = bob.balance; 386 | uint256 ruling = 1; 387 | vm.expectEmit(true, true, false, true); 388 | emit Ruling(arb, dispute, ruling); 389 | vm.prank(address(arb)); 390 | reps.rule(dispute, ruling); 391 | 392 | // ruling 1 consequences: pay bob the rep's pool, burn the NFT 393 | assertEq(bobBalance + payment1 + payment2, bob.balance, "bob balance"); 394 | assertEq(reps.ownerOf(rep), address(0), "rep owner"); 395 | } 396 | 397 | function testRule_Ruling2(uint64 payment) public { 398 | // set up and pay Rep 399 | (uint256 rep, bytes32 delegationId) = testSetRep(payment); 400 | address owner = reps.ownerOf(rep); 401 | uint256 fee = arb.arbitrationCost(""); 402 | 403 | // create dispute 404 | bob.call{value: 1 ether}(""); 405 | vm.expectEmit(true, true, false, false); 406 | emit DisputeCreation(0, reps); 407 | vm.prank(bob); 408 | uint256 dispute = reps.dispute{value: fee}(rep); 409 | checkDisputeData(rep, dispute, bob); 410 | 411 | // rule dispute 412 | uint256 bobBalance = bob.balance; 413 | uint256 ruling = 0; 414 | vm.expectEmit(true, true, false, true); 415 | emit Ruling(arb, dispute, ruling); 416 | vm.prank(address(arb)); 417 | reps.rule(dispute, ruling); 418 | 419 | // ruling 2 consequences: reset dispute, no other change 420 | assertEq(bobBalance, bob.balance, "bob balance"); 421 | assertEq(reps.ownerOf(rep), owner, "rep owner"); 422 | checkPaymentData(rep, block.timestamp, 0, payment, payment); 423 | checkDisputeData(rep, 0, address(0)); 424 | } 425 | 426 | function testFailRule_NonexistentDispute(uint64 payment) public { 427 | // set up and pay Rep 428 | (uint256 rep, bytes32 delegationId) = testSetRep(payment); 429 | address owner = reps.ownerOf(rep); 430 | uint256 fee = arb.arbitrationCost(""); 431 | 432 | // don't create dispute 433 | 434 | // try to rule nonexistent dispute 435 | uint256 bobBalance = bob.balance; 436 | uint256 ruling = 0; 437 | vm.prank(address(arb)); 438 | reps.rule(1, ruling); 439 | } 440 | 441 | function testFailRule_WrongCaller(uint64 payment) public { 442 | // set up and pay Rep 443 | (uint256 rep, bytes32 delegationId) = testSetRep(payment); 444 | address owner = reps.ownerOf(rep); 445 | uint256 fee = arb.arbitrationCost(""); 446 | 447 | // create dispute 448 | bob.call{value: 1 ether}(""); 449 | vm.expectEmit(true, true, false, false); 450 | emit DisputeCreation(0, reps); 451 | vm.prank(bob); 452 | uint256 dispute = reps.dispute{value: fee}(rep); 453 | checkDisputeData(rep, dispute, bob); 454 | 455 | // rule dispute 456 | uint256 bobBalance = bob.balance; 457 | uint256 ruling = 0; 458 | /* no prank(address(arb)) */ 459 | reps.rule(dispute, ruling); 460 | } 461 | } 462 | -------------------------------------------------------------------------------- /src/test/CentralizedArbitrator.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8; 3 | 4 | import "../IArbitrator.sol"; 5 | import "./console.sol"; 6 | 7 | /** @title Centralized Arbitrator 8 | * @dev This is a centralized arbitrator deciding alone on the result of disputes. It illustrates how IArbitrator interface can be implemented. 9 | * Note that this contract supports appeals. The ruling given by the arbitrator can be appealed by crowdfunding a desired choice. 10 | */ 11 | contract CentralizedArbitrator is IArbitrator { 12 | /* Constants */ 13 | 14 | // The required fee stake that a party must pay depends on who won the previous round and is proportional to the appeal cost such that the fee stake for a round is stake multiplier * appeal cost for that round. 15 | uint256 public constant WINNER_STAKE_MULTIPLIER = 10000; // Multiplier of the appeal cost that the winner has to pay as fee stake for a round in basis points. Default is 1x of appeal fee. 16 | uint256 public constant LOSER_STAKE_MULTIPLIER = 20000; // Multiplier of the appeal cost that the loser has to pay as fee stake for a round in basis points. Default is 2x of appeal fee. 17 | uint256 public constant LOSER_APPEAL_PERIOD_MULTIPLIER = 5000; // Multiplier of the appeal period for the choice that wasn't voted for in the previous round, in basis points. Default is 1/2 of original appeal period. 18 | uint256 public constant MULTIPLIER_DIVISOR = 10000; 19 | 20 | /* Enums */ 21 | 22 | enum DisputeStatus { 23 | Waiting, // The dispute is waiting for the ruling or not created. 24 | Appealable, // The dispute can be appealed. 25 | Solved // The dispute is resolved. 26 | } 27 | 28 | /* Structs */ 29 | 30 | struct DisputeStruct { 31 | IArbitrable arbitrated; // The address of the arbitrable contract. 32 | bytes arbitratorExtraData; // Extra data for the arbitrator. 33 | uint256 choices; // The number of choices the arbitrator can choose from. 34 | uint256 appealPeriodStart; // Time when the appeal funding becomes possible. 35 | uint256 arbitrationFee; // Fee paid by the arbitrable for the arbitration. Must be equal or higher than arbitration cost. 36 | uint256 ruling; // Ruling given by the arbitrator. 37 | DisputeStatus status; // A current status of the dispute. 38 | } 39 | 40 | struct Round { 41 | mapping(uint256 => uint256) paidFees; // Tracks the fees paid for each choice in this round. 42 | mapping(uint256 => bool) hasPaid; // True if this choice was fully funded, false otherwise. 43 | mapping(address => mapping(uint256 => uint256)) contributions; // Maps contributors to their contributions for each choice. 44 | uint256 feeRewards; // Sum of reimbursable appeal fees available to the parties that made contributions to the ruling that ultimately wins a dispute. 45 | uint256[] fundedChoices; // Stores the choices that are fully funded. 46 | } 47 | 48 | /* Storage */ 49 | 50 | address public owner = msg.sender; // Owner of the contract. 51 | uint256 public appealDuration; // The duration of the appeal period. 52 | 53 | uint256 private arbitrationFee; // The cost to create a dispute. Made private because of the arbitrationCost() getter. 54 | uint256 public appealFee; // The cost to fund one of the choices, not counting the additional fee stake amount. 55 | 56 | DisputeStruct[] public disputes; // Stores the dispute info. disputes[disputeID]. 57 | mapping(uint256 => Round[]) public disputeIDtoRoundArray; // Maps dispute IDs to Round array that contains the info about crowdfunding. 58 | 59 | /* Events */ 60 | 61 | /** 62 | * @dev To be emitted when a dispute can be appealed. 63 | * @param _disputeID ID of the dispute. 64 | * @param _arbitrable The contract which created the dispute. 65 | */ 66 | event AppealPossible( 67 | uint256 indexed _disputeID, 68 | IArbitrable indexed _arbitrable 69 | ); 70 | 71 | /** 72 | * @dev To be emitted when the current ruling is appealed. 73 | * @param _disputeID ID of the dispute. 74 | * @param _arbitrable The contract which created the dispute. 75 | */ 76 | event AppealDecision( 77 | uint256 indexed _disputeID, 78 | IArbitrable indexed _arbitrable 79 | ); 80 | 81 | /** @dev Raised when a contribution is made, inside fundAppeal function. 82 | * @param _disputeID ID of the dispute. 83 | * @param _round The round the contribution was made to. 84 | * @param _choice Indicates the choice option which got the contribution. 85 | * @param _contributor Caller of fundAppeal function. 86 | * @param _amount Contribution amount. 87 | */ 88 | event Contribution( 89 | uint256 indexed _disputeID, 90 | uint256 indexed _round, 91 | uint256 _choice, 92 | address indexed _contributor, 93 | uint256 _amount 94 | ); 95 | 96 | /** @dev Raised when a contributor withdraws a non-zero value. 97 | * @param _disputeID ID of the dispute. 98 | * @param _round The round the withdrawal was made from. 99 | * @param _choice Indicates the choice which contributor gets rewards from. 100 | * @param _contributor The beneficiary of the withdrawal. 101 | * @param _amount Total withdrawn amount, consists of reimbursed deposits and rewards. 102 | */ 103 | event Withdrawal( 104 | uint256 indexed _disputeID, 105 | uint256 indexed _round, 106 | uint256 _choice, 107 | address indexed _contributor, 108 | uint256 _amount 109 | ); 110 | 111 | /** @dev To be raised when a choice is fully funded for appeal. 112 | * @param _disputeID ID of the dispute. 113 | * @param _round ID of the round where the choice was funded. 114 | * @param _choice The choice that just got fully funded. 115 | */ 116 | event ChoiceFunded( 117 | uint256 indexed _disputeID, 118 | uint256 indexed _round, 119 | uint256 indexed _choice 120 | ); 121 | 122 | /* Modifiers */ 123 | 124 | modifier onlyOwner() { 125 | require(msg.sender == owner, "Can only be called by the owner."); 126 | _; 127 | } 128 | 129 | /** @dev Constructor. 130 | * @param _arbitrationFee Amount to be paid for arbitration. 131 | * @param _appealDuration Duration of the appeal period. 132 | * @param _appealFee Amount to be paid to fund one of the appeal choices, not counting the additional fee stake amount. 133 | */ 134 | constructor( 135 | uint256 _arbitrationFee, 136 | uint256 _appealDuration, 137 | uint256 _appealFee 138 | ) { 139 | arbitrationFee = _arbitrationFee; 140 | appealDuration = _appealDuration; 141 | appealFee = _appealFee; 142 | } 143 | 144 | /* External and Public */ 145 | 146 | /** @dev Set the arbitration fee. Only callable by the owner. 147 | * @param _arbitrationFee Amount to be paid for arbitration. 148 | */ 149 | function setArbitrationFee(uint256 _arbitrationFee) external onlyOwner { 150 | arbitrationFee = _arbitrationFee; 151 | } 152 | 153 | /** @dev Set the duration of the appeal period. Only callable by the owner. 154 | * @param _appealDuration New duration of the appeal period. 155 | */ 156 | function setAppealDuration(uint256 _appealDuration) external onlyOwner { 157 | appealDuration = _appealDuration; 158 | } 159 | 160 | /** @dev Set the appeal fee. Only callable by the owner. 161 | * @param _appealFee Amount to be paid for appeal. 162 | */ 163 | function setAppealFee(uint256 _appealFee) external onlyOwner { 164 | appealFee = _appealFee; 165 | } 166 | 167 | /** @dev Create a dispute. Must be called by the arbitrable contract. 168 | * Must be paid at least arbitrationCost(). 169 | * @param _choices Amount of choices the arbitrator can make in this dispute. 170 | * @param _extraData Can be used to give additional info on the dispute to be created. 171 | * @return disputeID ID of the dispute created. 172 | */ 173 | function createDispute(uint256 _choices, bytes calldata _extraData) 174 | external 175 | payable 176 | override 177 | returns (uint256 disputeID) 178 | { 179 | uint256 localArbitrationCost = arbitrationCost(_extraData); 180 | require( 181 | msg.value >= localArbitrationCost, 182 | "Not enough ETH to cover arbitration costs." 183 | ); 184 | disputeID = disputes.length; 185 | disputes.push( 186 | DisputeStruct({ 187 | arbitrated: IArbitrable(msg.sender), 188 | arbitratorExtraData: _extraData, 189 | choices: _choices, 190 | appealPeriodStart: 0, 191 | arbitrationFee: msg.value, 192 | ruling: 0, 193 | status: DisputeStatus.Waiting 194 | }) 195 | ); 196 | 197 | disputeIDtoRoundArray[disputeID].push(); 198 | emit DisputeCreation(disputeID, IArbitrable(msg.sender)); 199 | } 200 | 201 | /** @dev TRUSTED. Manages contributions, and appeals a dispute if at least two choices are fully funded. This function allows the appeals to be crowdfunded. 202 | * Note that the surplus deposit will be reimbursed. 203 | * @param _disputeID Index of the dispute to appeal. 204 | * @param _choice A choice that receives funding. 205 | */ 206 | function fundAppeal(uint256 _disputeID, uint256 _choice) external payable { 207 | DisputeStruct storage dispute = disputes[_disputeID]; 208 | require( 209 | dispute.status == DisputeStatus.Appealable, 210 | "Dispute not appealable." 211 | ); 212 | require(_choice <= dispute.choices, "There is no such ruling to fund."); 213 | 214 | (uint256 appealPeriodStart, uint256 appealPeriodEnd) = appealPeriod( 215 | _disputeID 216 | ); 217 | require( 218 | block.timestamp >= appealPeriodStart && 219 | block.timestamp < appealPeriodEnd, 220 | "Appeal period is over." 221 | ); 222 | 223 | uint256 multiplier; 224 | if (dispute.ruling == _choice) { 225 | multiplier = WINNER_STAKE_MULTIPLIER; 226 | } else { 227 | require( 228 | block.timestamp - appealPeriodStart < 229 | ((appealPeriodEnd - appealPeriodStart) * 230 | LOSER_APPEAL_PERIOD_MULTIPLIER) / 231 | MULTIPLIER_DIVISOR, 232 | "Appeal period is over for loser" 233 | ); 234 | multiplier = LOSER_STAKE_MULTIPLIER; 235 | } 236 | 237 | Round[] storage rounds = disputeIDtoRoundArray[_disputeID]; 238 | uint256 lastRoundIndex = rounds.length - 1; 239 | Round storage lastRound = rounds[lastRoundIndex]; 240 | require(!lastRound.hasPaid[_choice], "Appeal fee is already paid."); 241 | 242 | uint256 totalCost = appealFee + 243 | (appealFee * multiplier) / 244 | MULTIPLIER_DIVISOR; 245 | 246 | // Take up to the amount necessary to fund the current round at the current costs. 247 | uint256 contribution; 248 | if (totalCost > lastRound.paidFees[_choice]) { 249 | contribution = totalCost - lastRound.paidFees[_choice] > msg.value // Overflows and underflows will be managed on the compiler level. 250 | ? msg.value 251 | : totalCost - lastRound.paidFees[_choice]; 252 | emit Contribution( 253 | _disputeID, 254 | lastRoundIndex, 255 | _choice, 256 | msg.sender, 257 | contribution 258 | ); 259 | } 260 | 261 | lastRound.contributions[msg.sender][_choice] += contribution; 262 | lastRound.paidFees[_choice] += contribution; 263 | if (lastRound.paidFees[_choice] >= totalCost) { 264 | lastRound.feeRewards += lastRound.paidFees[_choice]; 265 | lastRound.fundedChoices.push(_choice); 266 | lastRound.hasPaid[_choice] = true; 267 | emit ChoiceFunded(_disputeID, lastRoundIndex, _choice); 268 | } 269 | 270 | if (lastRound.fundedChoices.length > 1) { 271 | // At least two sides are fully funded. 272 | rounds.push(); 273 | lastRound.feeRewards = lastRound.feeRewards - appealFee; 274 | 275 | dispute.status = DisputeStatus.Waiting; 276 | dispute.appealPeriodStart = 0; 277 | emit AppealDecision(_disputeID, dispute.arbitrated); 278 | } 279 | 280 | if (msg.value > contribution) 281 | payable(msg.sender).send(msg.value - contribution); 282 | } 283 | 284 | /** @dev Give a ruling to a dispute. Once it's given the dispute can be appealed, and after the appeal period has passed this function should be called again to finalize the ruling. 285 | * Accounts for the situation where the winner loses a case due to paying less appeal fees than expected. 286 | * @param _disputeID ID of the dispute to rule. 287 | * @param _ruling Ruling given by the arbitrator. Note that 0 means that arbitrator chose "Refused to rule". 288 | */ 289 | function giveRuling(uint256 _disputeID, uint256 _ruling) 290 | external 291 | onlyOwner 292 | { 293 | DisputeStruct storage dispute = disputes[_disputeID]; 294 | require(_ruling <= dispute.choices, "Invalid ruling."); 295 | require( 296 | dispute.status != DisputeStatus.Solved, 297 | "The dispute must not be solved." 298 | ); 299 | 300 | if (dispute.status == DisputeStatus.Waiting) { 301 | dispute.ruling = _ruling; 302 | dispute.status = DisputeStatus.Appealable; 303 | dispute.appealPeriodStart = block.timestamp; 304 | emit AppealPossible(_disputeID, dispute.arbitrated); 305 | } else { 306 | require( 307 | block.timestamp > dispute.appealPeriodStart + appealDuration, 308 | "Appeal period not passed yet." 309 | ); 310 | dispute.ruling = _ruling; 311 | dispute.status = DisputeStatus.Solved; 312 | 313 | Round[] storage rounds = disputeIDtoRoundArray[_disputeID]; 314 | Round storage lastRound = rounds[rounds.length - 1]; 315 | // If only one ruling option is funded, it wins by default. Note that if any other ruling had funded, an appeal would have been created. 316 | if (lastRound.fundedChoices.length == 1) { 317 | dispute.ruling = lastRound.fundedChoices[0]; 318 | } 319 | 320 | payable(msg.sender).send(dispute.arbitrationFee); // Avoid blocking. 321 | dispute.arbitrated.rule(_disputeID, dispute.ruling); 322 | } 323 | } 324 | 325 | /** @dev Allows to withdraw any reimbursable fees or rewards after the dispute gets resolved. 326 | * @param _disputeID Index of the dispute in disputes array. 327 | * @param _beneficiary The address which rewards to withdraw. 328 | * @param _round The round the caller wants to withdraw from. 329 | * @param _choice The ruling option that the caller wants to withdraw from. 330 | * @return amount The withdrawn amount. 331 | */ 332 | function withdrawFeesAndRewards( 333 | uint256 _disputeID, 334 | address payable _beneficiary, 335 | uint256 _round, 336 | uint256 _choice 337 | ) external returns (uint256 amount) { 338 | DisputeStruct storage dispute = disputes[_disputeID]; 339 | require( 340 | dispute.status == DisputeStatus.Solved, 341 | "Dispute should be resolved." 342 | ); 343 | Round storage round = disputeIDtoRoundArray[_disputeID][_round]; 344 | 345 | if (!round.hasPaid[_choice]) { 346 | // Allow to reimburse if funding was unsuccessful for this ruling option. 347 | amount = round.contributions[_beneficiary][_choice]; 348 | } else { 349 | // Funding was successful for this ruling option. 350 | if (_choice == dispute.ruling) { 351 | // This ruling option is the ultimate winner. 352 | amount = round.paidFees[_choice] > 0 353 | ? (round.contributions[_beneficiary][_choice] * 354 | round.feeRewards) / round.paidFees[_choice] 355 | : 0; 356 | } else if (!round.hasPaid[dispute.ruling]) { 357 | // The ultimate winner was not funded in this round. In this case funded ruling option(s) are reimbursed. 358 | amount = 359 | (round.contributions[_beneficiary][_choice] * 360 | round.feeRewards) / 361 | (round.paidFees[round.fundedChoices[0]] + 362 | round.paidFees[round.fundedChoices[1]]); 363 | } 364 | } 365 | round.contributions[_beneficiary][_choice] = 0; 366 | 367 | if (amount != 0) { 368 | _beneficiary.send(amount); // Deliberate use of send to prevent reverting fallback. It's the user's responsibility to accept ETH. 369 | emit Withdrawal(_disputeID, _round, _choice, _beneficiary, amount); 370 | } 371 | } 372 | 373 | // ************************ // 374 | // * Getters * // 375 | // ************************ // 376 | 377 | /** @dev Cost of arbitration. 378 | * @return fee The required amount. 379 | */ 380 | function arbitrationCost( 381 | bytes calldata /*_extraData*/ 382 | ) public view override returns (uint256 fee) { 383 | return arbitrationFee; 384 | } 385 | 386 | /** @dev Return the funded amount and funding goal for one of the choices. 387 | * @param _disputeID The ID of the dispute to appeal. 388 | * @param _choice The choice to check the funding status of. 389 | * @return funded The amount funded so far for this choice in wei. 390 | * @return goal The amount to fully fund this choice in wei. 391 | */ 392 | function fundingStatus(uint256 _disputeID, uint256 _choice) 393 | external 394 | view 395 | returns (uint256 funded, uint256 goal) 396 | { 397 | DisputeStruct storage dispute = disputes[_disputeID]; 398 | require(_choice <= dispute.choices, "There is no such ruling to fund."); 399 | require( 400 | dispute.status == DisputeStatus.Appealable, 401 | "Dispute not appealable." 402 | ); 403 | 404 | if (dispute.ruling == _choice) { 405 | goal = 406 | appealFee + 407 | (appealFee * WINNER_STAKE_MULTIPLIER) / 408 | MULTIPLIER_DIVISOR; 409 | } else { 410 | goal = 411 | appealFee + 412 | (appealFee * LOSER_STAKE_MULTIPLIER) / 413 | MULTIPLIER_DIVISOR; 414 | } 415 | 416 | Round[] storage rounds = disputeIDtoRoundArray[_disputeID]; 417 | Round storage lastRound = rounds[rounds.length - 1]; 418 | 419 | return (lastRound.paidFees[_choice], goal); 420 | } 421 | 422 | /** @dev Compute the start and end of the dispute's appeal period, if possible. If the dispute is not appealble return (0, 0). 423 | * @param _disputeID ID of the dispute. 424 | * @return start The start of the period. 425 | * @return end The end of the period. 426 | */ 427 | function appealPeriod(uint256 _disputeID) 428 | public 429 | view 430 | returns (uint256 start, uint256 end) 431 | { 432 | DisputeStruct storage dispute = disputes[_disputeID]; 433 | if (dispute.status == DisputeStatus.Appealable) { 434 | start = dispute.appealPeriodStart; 435 | end = start + appealDuration; 436 | } 437 | return (start, end); 438 | } 439 | } 440 | -------------------------------------------------------------------------------- /src/test/console.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.4.22 <0.9.0; 3 | 4 | library console { 5 | address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67); 6 | 7 | function _sendLogPayload(bytes memory payload) private view { 8 | uint256 payloadLength = payload.length; 9 | address consoleAddress = CONSOLE_ADDRESS; 10 | assembly { 11 | let payloadStart := add(payload, 32) 12 | let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0) 13 | } 14 | } 15 | 16 | function log() internal view { 17 | _sendLogPayload(abi.encodeWithSignature("log()")); 18 | } 19 | 20 | function logInt(int p0) internal view { 21 | _sendLogPayload(abi.encodeWithSignature("log(int)", p0)); 22 | } 23 | 24 | function logUint(uint p0) internal view { 25 | _sendLogPayload(abi.encodeWithSignature("log(uint)", p0)); 26 | } 27 | 28 | function logString(string memory p0) internal view { 29 | _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); 30 | } 31 | 32 | function logBool(bool p0) internal view { 33 | _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); 34 | } 35 | 36 | function logAddress(address p0) internal view { 37 | _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); 38 | } 39 | 40 | function logBytes(bytes memory p0) internal view { 41 | _sendLogPayload(abi.encodeWithSignature("log(bytes)", p0)); 42 | } 43 | 44 | function logBytes1(bytes1 p0) internal view { 45 | _sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0)); 46 | } 47 | 48 | function logBytes2(bytes2 p0) internal view { 49 | _sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0)); 50 | } 51 | 52 | function logBytes3(bytes3 p0) internal view { 53 | _sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0)); 54 | } 55 | 56 | function logBytes4(bytes4 p0) internal view { 57 | _sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0)); 58 | } 59 | 60 | function logBytes5(bytes5 p0) internal view { 61 | _sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0)); 62 | } 63 | 64 | function logBytes6(bytes6 p0) internal view { 65 | _sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0)); 66 | } 67 | 68 | function logBytes7(bytes7 p0) internal view { 69 | _sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0)); 70 | } 71 | 72 | function logBytes8(bytes8 p0) internal view { 73 | _sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0)); 74 | } 75 | 76 | function logBytes9(bytes9 p0) internal view { 77 | _sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0)); 78 | } 79 | 80 | function logBytes10(bytes10 p0) internal view { 81 | _sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0)); 82 | } 83 | 84 | function logBytes11(bytes11 p0) internal view { 85 | _sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0)); 86 | } 87 | 88 | function logBytes12(bytes12 p0) internal view { 89 | _sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0)); 90 | } 91 | 92 | function logBytes13(bytes13 p0) internal view { 93 | _sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0)); 94 | } 95 | 96 | function logBytes14(bytes14 p0) internal view { 97 | _sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0)); 98 | } 99 | 100 | function logBytes15(bytes15 p0) internal view { 101 | _sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0)); 102 | } 103 | 104 | function logBytes16(bytes16 p0) internal view { 105 | _sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0)); 106 | } 107 | 108 | function logBytes17(bytes17 p0) internal view { 109 | _sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0)); 110 | } 111 | 112 | function logBytes18(bytes18 p0) internal view { 113 | _sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0)); 114 | } 115 | 116 | function logBytes19(bytes19 p0) internal view { 117 | _sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0)); 118 | } 119 | 120 | function logBytes20(bytes20 p0) internal view { 121 | _sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0)); 122 | } 123 | 124 | function logBytes21(bytes21 p0) internal view { 125 | _sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0)); 126 | } 127 | 128 | function logBytes22(bytes22 p0) internal view { 129 | _sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0)); 130 | } 131 | 132 | function logBytes23(bytes23 p0) internal view { 133 | _sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0)); 134 | } 135 | 136 | function logBytes24(bytes24 p0) internal view { 137 | _sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0)); 138 | } 139 | 140 | function logBytes25(bytes25 p0) internal view { 141 | _sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0)); 142 | } 143 | 144 | function logBytes26(bytes26 p0) internal view { 145 | _sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0)); 146 | } 147 | 148 | function logBytes27(bytes27 p0) internal view { 149 | _sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0)); 150 | } 151 | 152 | function logBytes28(bytes28 p0) internal view { 153 | _sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0)); 154 | } 155 | 156 | function logBytes29(bytes29 p0) internal view { 157 | _sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0)); 158 | } 159 | 160 | function logBytes30(bytes30 p0) internal view { 161 | _sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0)); 162 | } 163 | 164 | function logBytes31(bytes31 p0) internal view { 165 | _sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0)); 166 | } 167 | 168 | function logBytes32(bytes32 p0) internal view { 169 | _sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0)); 170 | } 171 | 172 | function log(uint p0) internal view { 173 | _sendLogPayload(abi.encodeWithSignature("log(uint)", p0)); 174 | } 175 | 176 | function log(string memory p0) internal view { 177 | _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); 178 | } 179 | 180 | function log(bool p0) internal view { 181 | _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); 182 | } 183 | 184 | function log(address p0) internal view { 185 | _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); 186 | } 187 | 188 | function log(uint p0, uint p1) internal view { 189 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint)", p0, p1)); 190 | } 191 | 192 | function log(uint p0, string memory p1) internal view { 193 | _sendLogPayload(abi.encodeWithSignature("log(uint,string)", p0, p1)); 194 | } 195 | 196 | function log(uint p0, bool p1) internal view { 197 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool)", p0, p1)); 198 | } 199 | 200 | function log(uint p0, address p1) internal view { 201 | _sendLogPayload(abi.encodeWithSignature("log(uint,address)", p0, p1)); 202 | } 203 | 204 | function log(string memory p0, uint p1) internal view { 205 | _sendLogPayload(abi.encodeWithSignature("log(string,uint)", p0, p1)); 206 | } 207 | 208 | function log(string memory p0, string memory p1) internal view { 209 | _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1)); 210 | } 211 | 212 | function log(string memory p0, bool p1) internal view { 213 | _sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1)); 214 | } 215 | 216 | function log(string memory p0, address p1) internal view { 217 | _sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1)); 218 | } 219 | 220 | function log(bool p0, uint p1) internal view { 221 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint)", p0, p1)); 222 | } 223 | 224 | function log(bool p0, string memory p1) internal view { 225 | _sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1)); 226 | } 227 | 228 | function log(bool p0, bool p1) internal view { 229 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1)); 230 | } 231 | 232 | function log(bool p0, address p1) internal view { 233 | _sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1)); 234 | } 235 | 236 | function log(address p0, uint p1) internal view { 237 | _sendLogPayload(abi.encodeWithSignature("log(address,uint)", p0, p1)); 238 | } 239 | 240 | function log(address p0, string memory p1) internal view { 241 | _sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1)); 242 | } 243 | 244 | function log(address p0, bool p1) internal view { 245 | _sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1)); 246 | } 247 | 248 | function log(address p0, address p1) internal view { 249 | _sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1)); 250 | } 251 | 252 | function log(uint p0, uint p1, uint p2) internal view { 253 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint)", p0, p1, p2)); 254 | } 255 | 256 | function log(uint p0, uint p1, string memory p2) internal view { 257 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string)", p0, p1, p2)); 258 | } 259 | 260 | function log(uint p0, uint p1, bool p2) internal view { 261 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool)", p0, p1, p2)); 262 | } 263 | 264 | function log(uint p0, uint p1, address p2) internal view { 265 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address)", p0, p1, p2)); 266 | } 267 | 268 | function log(uint p0, string memory p1, uint p2) internal view { 269 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint)", p0, p1, p2)); 270 | } 271 | 272 | function log(uint p0, string memory p1, string memory p2) internal view { 273 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,string)", p0, p1, p2)); 274 | } 275 | 276 | function log(uint p0, string memory p1, bool p2) internal view { 277 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool)", p0, p1, p2)); 278 | } 279 | 280 | function log(uint p0, string memory p1, address p2) internal view { 281 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,address)", p0, p1, p2)); 282 | } 283 | 284 | function log(uint p0, bool p1, uint p2) internal view { 285 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint)", p0, p1, p2)); 286 | } 287 | 288 | function log(uint p0, bool p1, string memory p2) internal view { 289 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string)", p0, p1, p2)); 290 | } 291 | 292 | function log(uint p0, bool p1, bool p2) internal view { 293 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool)", p0, p1, p2)); 294 | } 295 | 296 | function log(uint p0, bool p1, address p2) internal view { 297 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address)", p0, p1, p2)); 298 | } 299 | 300 | function log(uint p0, address p1, uint p2) internal view { 301 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint)", p0, p1, p2)); 302 | } 303 | 304 | function log(uint p0, address p1, string memory p2) internal view { 305 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,string)", p0, p1, p2)); 306 | } 307 | 308 | function log(uint p0, address p1, bool p2) internal view { 309 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool)", p0, p1, p2)); 310 | } 311 | 312 | function log(uint p0, address p1, address p2) internal view { 313 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,address)", p0, p1, p2)); 314 | } 315 | 316 | function log(string memory p0, uint p1, uint p2) internal view { 317 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint)", p0, p1, p2)); 318 | } 319 | 320 | function log(string memory p0, uint p1, string memory p2) internal view { 321 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,string)", p0, p1, p2)); 322 | } 323 | 324 | function log(string memory p0, uint p1, bool p2) internal view { 325 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool)", p0, p1, p2)); 326 | } 327 | 328 | function log(string memory p0, uint p1, address p2) internal view { 329 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,address)", p0, p1, p2)); 330 | } 331 | 332 | function log(string memory p0, string memory p1, uint p2) internal view { 333 | _sendLogPayload(abi.encodeWithSignature("log(string,string,uint)", p0, p1, p2)); 334 | } 335 | 336 | function log(string memory p0, string memory p1, string memory p2) internal view { 337 | _sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2)); 338 | } 339 | 340 | function log(string memory p0, string memory p1, bool p2) internal view { 341 | _sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2)); 342 | } 343 | 344 | function log(string memory p0, string memory p1, address p2) internal view { 345 | _sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2)); 346 | } 347 | 348 | function log(string memory p0, bool p1, uint p2) internal view { 349 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint)", p0, p1, p2)); 350 | } 351 | 352 | function log(string memory p0, bool p1, string memory p2) internal view { 353 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2)); 354 | } 355 | 356 | function log(string memory p0, bool p1, bool p2) internal view { 357 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2)); 358 | } 359 | 360 | function log(string memory p0, bool p1, address p2) internal view { 361 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2)); 362 | } 363 | 364 | function log(string memory p0, address p1, uint p2) internal view { 365 | _sendLogPayload(abi.encodeWithSignature("log(string,address,uint)", p0, p1, p2)); 366 | } 367 | 368 | function log(string memory p0, address p1, string memory p2) internal view { 369 | _sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2)); 370 | } 371 | 372 | function log(string memory p0, address p1, bool p2) internal view { 373 | _sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2)); 374 | } 375 | 376 | function log(string memory p0, address p1, address p2) internal view { 377 | _sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2)); 378 | } 379 | 380 | function log(bool p0, uint p1, uint p2) internal view { 381 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint)", p0, p1, p2)); 382 | } 383 | 384 | function log(bool p0, uint p1, string memory p2) internal view { 385 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string)", p0, p1, p2)); 386 | } 387 | 388 | function log(bool p0, uint p1, bool p2) internal view { 389 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool)", p0, p1, p2)); 390 | } 391 | 392 | function log(bool p0, uint p1, address p2) internal view { 393 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address)", p0, p1, p2)); 394 | } 395 | 396 | function log(bool p0, string memory p1, uint p2) internal view { 397 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint)", p0, p1, p2)); 398 | } 399 | 400 | function log(bool p0, string memory p1, string memory p2) internal view { 401 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2)); 402 | } 403 | 404 | function log(bool p0, string memory p1, bool p2) internal view { 405 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2)); 406 | } 407 | 408 | function log(bool p0, string memory p1, address p2) internal view { 409 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2)); 410 | } 411 | 412 | function log(bool p0, bool p1, uint p2) internal view { 413 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint)", p0, p1, p2)); 414 | } 415 | 416 | function log(bool p0, bool p1, string memory p2) internal view { 417 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2)); 418 | } 419 | 420 | function log(bool p0, bool p1, bool p2) internal view { 421 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2)); 422 | } 423 | 424 | function log(bool p0, bool p1, address p2) internal view { 425 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2)); 426 | } 427 | 428 | function log(bool p0, address p1, uint p2) internal view { 429 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint)", p0, p1, p2)); 430 | } 431 | 432 | function log(bool p0, address p1, string memory p2) internal view { 433 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2)); 434 | } 435 | 436 | function log(bool p0, address p1, bool p2) internal view { 437 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2)); 438 | } 439 | 440 | function log(bool p0, address p1, address p2) internal view { 441 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2)); 442 | } 443 | 444 | function log(address p0, uint p1, uint p2) internal view { 445 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint)", p0, p1, p2)); 446 | } 447 | 448 | function log(address p0, uint p1, string memory p2) internal view { 449 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,string)", p0, p1, p2)); 450 | } 451 | 452 | function log(address p0, uint p1, bool p2) internal view { 453 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool)", p0, p1, p2)); 454 | } 455 | 456 | function log(address p0, uint p1, address p2) internal view { 457 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,address)", p0, p1, p2)); 458 | } 459 | 460 | function log(address p0, string memory p1, uint p2) internal view { 461 | _sendLogPayload(abi.encodeWithSignature("log(address,string,uint)", p0, p1, p2)); 462 | } 463 | 464 | function log(address p0, string memory p1, string memory p2) internal view { 465 | _sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2)); 466 | } 467 | 468 | function log(address p0, string memory p1, bool p2) internal view { 469 | _sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2)); 470 | } 471 | 472 | function log(address p0, string memory p1, address p2) internal view { 473 | _sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2)); 474 | } 475 | 476 | function log(address p0, bool p1, uint p2) internal view { 477 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint)", p0, p1, p2)); 478 | } 479 | 480 | function log(address p0, bool p1, string memory p2) internal view { 481 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2)); 482 | } 483 | 484 | function log(address p0, bool p1, bool p2) internal view { 485 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2)); 486 | } 487 | 488 | function log(address p0, bool p1, address p2) internal view { 489 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2)); 490 | } 491 | 492 | function log(address p0, address p1, uint p2) internal view { 493 | _sendLogPayload(abi.encodeWithSignature("log(address,address,uint)", p0, p1, p2)); 494 | } 495 | 496 | function log(address p0, address p1, string memory p2) internal view { 497 | _sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2)); 498 | } 499 | 500 | function log(address p0, address p1, bool p2) internal view { 501 | _sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2)); 502 | } 503 | 504 | function log(address p0, address p1, address p2) internal view { 505 | _sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2)); 506 | } 507 | 508 | function log(uint p0, uint p1, uint p2, uint p3) internal view { 509 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,uint)", p0, p1, p2, p3)); 510 | } 511 | 512 | function log(uint p0, uint p1, uint p2, string memory p3) internal view { 513 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,string)", p0, p1, p2, p3)); 514 | } 515 | 516 | function log(uint p0, uint p1, uint p2, bool p3) internal view { 517 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,bool)", p0, p1, p2, p3)); 518 | } 519 | 520 | function log(uint p0, uint p1, uint p2, address p3) internal view { 521 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,address)", p0, p1, p2, p3)); 522 | } 523 | 524 | function log(uint p0, uint p1, string memory p2, uint p3) internal view { 525 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,uint)", p0, p1, p2, p3)); 526 | } 527 | 528 | function log(uint p0, uint p1, string memory p2, string memory p3) internal view { 529 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,string)", p0, p1, p2, p3)); 530 | } 531 | 532 | function log(uint p0, uint p1, string memory p2, bool p3) internal view { 533 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,bool)", p0, p1, p2, p3)); 534 | } 535 | 536 | function log(uint p0, uint p1, string memory p2, address p3) internal view { 537 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,address)", p0, p1, p2, p3)); 538 | } 539 | 540 | function log(uint p0, uint p1, bool p2, uint p3) internal view { 541 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,uint)", p0, p1, p2, p3)); 542 | } 543 | 544 | function log(uint p0, uint p1, bool p2, string memory p3) internal view { 545 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,string)", p0, p1, p2, p3)); 546 | } 547 | 548 | function log(uint p0, uint p1, bool p2, bool p3) internal view { 549 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,bool)", p0, p1, p2, p3)); 550 | } 551 | 552 | function log(uint p0, uint p1, bool p2, address p3) internal view { 553 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,address)", p0, p1, p2, p3)); 554 | } 555 | 556 | function log(uint p0, uint p1, address p2, uint p3) internal view { 557 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,uint)", p0, p1, p2, p3)); 558 | } 559 | 560 | function log(uint p0, uint p1, address p2, string memory p3) internal view { 561 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,string)", p0, p1, p2, p3)); 562 | } 563 | 564 | function log(uint p0, uint p1, address p2, bool p3) internal view { 565 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,bool)", p0, p1, p2, p3)); 566 | } 567 | 568 | function log(uint p0, uint p1, address p2, address p3) internal view { 569 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,address)", p0, p1, p2, p3)); 570 | } 571 | 572 | function log(uint p0, string memory p1, uint p2, uint p3) internal view { 573 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,uint)", p0, p1, p2, p3)); 574 | } 575 | 576 | function log(uint p0, string memory p1, uint p2, string memory p3) internal view { 577 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,string)", p0, p1, p2, p3)); 578 | } 579 | 580 | function log(uint p0, string memory p1, uint p2, bool p3) internal view { 581 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,bool)", p0, p1, p2, p3)); 582 | } 583 | 584 | function log(uint p0, string memory p1, uint p2, address p3) internal view { 585 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,address)", p0, p1, p2, p3)); 586 | } 587 | 588 | function log(uint p0, string memory p1, string memory p2, uint p3) internal view { 589 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,uint)", p0, p1, p2, p3)); 590 | } 591 | 592 | function log(uint p0, string memory p1, string memory p2, string memory p3) internal view { 593 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,string)", p0, p1, p2, p3)); 594 | } 595 | 596 | function log(uint p0, string memory p1, string memory p2, bool p3) internal view { 597 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,bool)", p0, p1, p2, p3)); 598 | } 599 | 600 | function log(uint p0, string memory p1, string memory p2, address p3) internal view { 601 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,address)", p0, p1, p2, p3)); 602 | } 603 | 604 | function log(uint p0, string memory p1, bool p2, uint p3) internal view { 605 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,uint)", p0, p1, p2, p3)); 606 | } 607 | 608 | function log(uint p0, string memory p1, bool p2, string memory p3) internal view { 609 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,string)", p0, p1, p2, p3)); 610 | } 611 | 612 | function log(uint p0, string memory p1, bool p2, bool p3) internal view { 613 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,bool)", p0, p1, p2, p3)); 614 | } 615 | 616 | function log(uint p0, string memory p1, bool p2, address p3) internal view { 617 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,address)", p0, p1, p2, p3)); 618 | } 619 | 620 | function log(uint p0, string memory p1, address p2, uint p3) internal view { 621 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,uint)", p0, p1, p2, p3)); 622 | } 623 | 624 | function log(uint p0, string memory p1, address p2, string memory p3) internal view { 625 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,string)", p0, p1, p2, p3)); 626 | } 627 | 628 | function log(uint p0, string memory p1, address p2, bool p3) internal view { 629 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,bool)", p0, p1, p2, p3)); 630 | } 631 | 632 | function log(uint p0, string memory p1, address p2, address p3) internal view { 633 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,address)", p0, p1, p2, p3)); 634 | } 635 | 636 | function log(uint p0, bool p1, uint p2, uint p3) internal view { 637 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,uint)", p0, p1, p2, p3)); 638 | } 639 | 640 | function log(uint p0, bool p1, uint p2, string memory p3) internal view { 641 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,string)", p0, p1, p2, p3)); 642 | } 643 | 644 | function log(uint p0, bool p1, uint p2, bool p3) internal view { 645 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,bool)", p0, p1, p2, p3)); 646 | } 647 | 648 | function log(uint p0, bool p1, uint p2, address p3) internal view { 649 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,address)", p0, p1, p2, p3)); 650 | } 651 | 652 | function log(uint p0, bool p1, string memory p2, uint p3) internal view { 653 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,uint)", p0, p1, p2, p3)); 654 | } 655 | 656 | function log(uint p0, bool p1, string memory p2, string memory p3) internal view { 657 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,string)", p0, p1, p2, p3)); 658 | } 659 | 660 | function log(uint p0, bool p1, string memory p2, bool p3) internal view { 661 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,bool)", p0, p1, p2, p3)); 662 | } 663 | 664 | function log(uint p0, bool p1, string memory p2, address p3) internal view { 665 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,address)", p0, p1, p2, p3)); 666 | } 667 | 668 | function log(uint p0, bool p1, bool p2, uint p3) internal view { 669 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,uint)", p0, p1, p2, p3)); 670 | } 671 | 672 | function log(uint p0, bool p1, bool p2, string memory p3) internal view { 673 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,string)", p0, p1, p2, p3)); 674 | } 675 | 676 | function log(uint p0, bool p1, bool p2, bool p3) internal view { 677 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,bool)", p0, p1, p2, p3)); 678 | } 679 | 680 | function log(uint p0, bool p1, bool p2, address p3) internal view { 681 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,address)", p0, p1, p2, p3)); 682 | } 683 | 684 | function log(uint p0, bool p1, address p2, uint p3) internal view { 685 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,uint)", p0, p1, p2, p3)); 686 | } 687 | 688 | function log(uint p0, bool p1, address p2, string memory p3) internal view { 689 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,string)", p0, p1, p2, p3)); 690 | } 691 | 692 | function log(uint p0, bool p1, address p2, bool p3) internal view { 693 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,bool)", p0, p1, p2, p3)); 694 | } 695 | 696 | function log(uint p0, bool p1, address p2, address p3) internal view { 697 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,address)", p0, p1, p2, p3)); 698 | } 699 | 700 | function log(uint p0, address p1, uint p2, uint p3) internal view { 701 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,uint)", p0, p1, p2, p3)); 702 | } 703 | 704 | function log(uint p0, address p1, uint p2, string memory p3) internal view { 705 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,string)", p0, p1, p2, p3)); 706 | } 707 | 708 | function log(uint p0, address p1, uint p2, bool p3) internal view { 709 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,bool)", p0, p1, p2, p3)); 710 | } 711 | 712 | function log(uint p0, address p1, uint p2, address p3) internal view { 713 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,address)", p0, p1, p2, p3)); 714 | } 715 | 716 | function log(uint p0, address p1, string memory p2, uint p3) internal view { 717 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,uint)", p0, p1, p2, p3)); 718 | } 719 | 720 | function log(uint p0, address p1, string memory p2, string memory p3) internal view { 721 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,string)", p0, p1, p2, p3)); 722 | } 723 | 724 | function log(uint p0, address p1, string memory p2, bool p3) internal view { 725 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,bool)", p0, p1, p2, p3)); 726 | } 727 | 728 | function log(uint p0, address p1, string memory p2, address p3) internal view { 729 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,address)", p0, p1, p2, p3)); 730 | } 731 | 732 | function log(uint p0, address p1, bool p2, uint p3) internal view { 733 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,uint)", p0, p1, p2, p3)); 734 | } 735 | 736 | function log(uint p0, address p1, bool p2, string memory p3) internal view { 737 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,string)", p0, p1, p2, p3)); 738 | } 739 | 740 | function log(uint p0, address p1, bool p2, bool p3) internal view { 741 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,bool)", p0, p1, p2, p3)); 742 | } 743 | 744 | function log(uint p0, address p1, bool p2, address p3) internal view { 745 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,address)", p0, p1, p2, p3)); 746 | } 747 | 748 | function log(uint p0, address p1, address p2, uint p3) internal view { 749 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,uint)", p0, p1, p2, p3)); 750 | } 751 | 752 | function log(uint p0, address p1, address p2, string memory p3) internal view { 753 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,string)", p0, p1, p2, p3)); 754 | } 755 | 756 | function log(uint p0, address p1, address p2, bool p3) internal view { 757 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,bool)", p0, p1, p2, p3)); 758 | } 759 | 760 | function log(uint p0, address p1, address p2, address p3) internal view { 761 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,address)", p0, p1, p2, p3)); 762 | } 763 | 764 | function log(string memory p0, uint p1, uint p2, uint p3) internal view { 765 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,uint)", p0, p1, p2, p3)); 766 | } 767 | 768 | function log(string memory p0, uint p1, uint p2, string memory p3) internal view { 769 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,string)", p0, p1, p2, p3)); 770 | } 771 | 772 | function log(string memory p0, uint p1, uint p2, bool p3) internal view { 773 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,bool)", p0, p1, p2, p3)); 774 | } 775 | 776 | function log(string memory p0, uint p1, uint p2, address p3) internal view { 777 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,address)", p0, p1, p2, p3)); 778 | } 779 | 780 | function log(string memory p0, uint p1, string memory p2, uint p3) internal view { 781 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,uint)", p0, p1, p2, p3)); 782 | } 783 | 784 | function log(string memory p0, uint p1, string memory p2, string memory p3) internal view { 785 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,string)", p0, p1, p2, p3)); 786 | } 787 | 788 | function log(string memory p0, uint p1, string memory p2, bool p3) internal view { 789 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,bool)", p0, p1, p2, p3)); 790 | } 791 | 792 | function log(string memory p0, uint p1, string memory p2, address p3) internal view { 793 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,address)", p0, p1, p2, p3)); 794 | } 795 | 796 | function log(string memory p0, uint p1, bool p2, uint p3) internal view { 797 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,uint)", p0, p1, p2, p3)); 798 | } 799 | 800 | function log(string memory p0, uint p1, bool p2, string memory p3) internal view { 801 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,string)", p0, p1, p2, p3)); 802 | } 803 | 804 | function log(string memory p0, uint p1, bool p2, bool p3) internal view { 805 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,bool)", p0, p1, p2, p3)); 806 | } 807 | 808 | function log(string memory p0, uint p1, bool p2, address p3) internal view { 809 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,address)", p0, p1, p2, p3)); 810 | } 811 | 812 | function log(string memory p0, uint p1, address p2, uint p3) internal view { 813 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,uint)", p0, p1, p2, p3)); 814 | } 815 | 816 | function log(string memory p0, uint p1, address p2, string memory p3) internal view { 817 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,string)", p0, p1, p2, p3)); 818 | } 819 | 820 | function log(string memory p0, uint p1, address p2, bool p3) internal view { 821 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,bool)", p0, p1, p2, p3)); 822 | } 823 | 824 | function log(string memory p0, uint p1, address p2, address p3) internal view { 825 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,address)", p0, p1, p2, p3)); 826 | } 827 | 828 | function log(string memory p0, string memory p1, uint p2, uint p3) internal view { 829 | _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,uint)", p0, p1, p2, p3)); 830 | } 831 | 832 | function log(string memory p0, string memory p1, uint p2, string memory p3) internal view { 833 | _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,string)", p0, p1, p2, p3)); 834 | } 835 | 836 | function log(string memory p0, string memory p1, uint p2, bool p3) internal view { 837 | _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,bool)", p0, p1, p2, p3)); 838 | } 839 | 840 | function log(string memory p0, string memory p1, uint p2, address p3) internal view { 841 | _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,address)", p0, p1, p2, p3)); 842 | } 843 | 844 | function log(string memory p0, string memory p1, string memory p2, uint p3) internal view { 845 | _sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint)", p0, p1, p2, p3)); 846 | } 847 | 848 | function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view { 849 | _sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3)); 850 | } 851 | 852 | function log(string memory p0, string memory p1, string memory p2, bool p3) internal view { 853 | _sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3)); 854 | } 855 | 856 | function log(string memory p0, string memory p1, string memory p2, address p3) internal view { 857 | _sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3)); 858 | } 859 | 860 | function log(string memory p0, string memory p1, bool p2, uint p3) internal view { 861 | _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint)", p0, p1, p2, p3)); 862 | } 863 | 864 | function log(string memory p0, string memory p1, bool p2, string memory p3) internal view { 865 | _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3)); 866 | } 867 | 868 | function log(string memory p0, string memory p1, bool p2, bool p3) internal view { 869 | _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3)); 870 | } 871 | 872 | function log(string memory p0, string memory p1, bool p2, address p3) internal view { 873 | _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3)); 874 | } 875 | 876 | function log(string memory p0, string memory p1, address p2, uint p3) internal view { 877 | _sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint)", p0, p1, p2, p3)); 878 | } 879 | 880 | function log(string memory p0, string memory p1, address p2, string memory p3) internal view { 881 | _sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3)); 882 | } 883 | 884 | function log(string memory p0, string memory p1, address p2, bool p3) internal view { 885 | _sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3)); 886 | } 887 | 888 | function log(string memory p0, string memory p1, address p2, address p3) internal view { 889 | _sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3)); 890 | } 891 | 892 | function log(string memory p0, bool p1, uint p2, uint p3) internal view { 893 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,uint)", p0, p1, p2, p3)); 894 | } 895 | 896 | function log(string memory p0, bool p1, uint p2, string memory p3) internal view { 897 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,string)", p0, p1, p2, p3)); 898 | } 899 | 900 | function log(string memory p0, bool p1, uint p2, bool p3) internal view { 901 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,bool)", p0, p1, p2, p3)); 902 | } 903 | 904 | function log(string memory p0, bool p1, uint p2, address p3) internal view { 905 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,address)", p0, p1, p2, p3)); 906 | } 907 | 908 | function log(string memory p0, bool p1, string memory p2, uint p3) internal view { 909 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint)", p0, p1, p2, p3)); 910 | } 911 | 912 | function log(string memory p0, bool p1, string memory p2, string memory p3) internal view { 913 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3)); 914 | } 915 | 916 | function log(string memory p0, bool p1, string memory p2, bool p3) internal view { 917 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3)); 918 | } 919 | 920 | function log(string memory p0, bool p1, string memory p2, address p3) internal view { 921 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3)); 922 | } 923 | 924 | function log(string memory p0, bool p1, bool p2, uint p3) internal view { 925 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint)", p0, p1, p2, p3)); 926 | } 927 | 928 | function log(string memory p0, bool p1, bool p2, string memory p3) internal view { 929 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3)); 930 | } 931 | 932 | function log(string memory p0, bool p1, bool p2, bool p3) internal view { 933 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3)); 934 | } 935 | 936 | function log(string memory p0, bool p1, bool p2, address p3) internal view { 937 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3)); 938 | } 939 | 940 | function log(string memory p0, bool p1, address p2, uint p3) internal view { 941 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint)", p0, p1, p2, p3)); 942 | } 943 | 944 | function log(string memory p0, bool p1, address p2, string memory p3) internal view { 945 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3)); 946 | } 947 | 948 | function log(string memory p0, bool p1, address p2, bool p3) internal view { 949 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3)); 950 | } 951 | 952 | function log(string memory p0, bool p1, address p2, address p3) internal view { 953 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3)); 954 | } 955 | 956 | function log(string memory p0, address p1, uint p2, uint p3) internal view { 957 | _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,uint)", p0, p1, p2, p3)); 958 | } 959 | 960 | function log(string memory p0, address p1, uint p2, string memory p3) internal view { 961 | _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,string)", p0, p1, p2, p3)); 962 | } 963 | 964 | function log(string memory p0, address p1, uint p2, bool p3) internal view { 965 | _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,bool)", p0, p1, p2, p3)); 966 | } 967 | 968 | function log(string memory p0, address p1, uint p2, address p3) internal view { 969 | _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,address)", p0, p1, p2, p3)); 970 | } 971 | 972 | function log(string memory p0, address p1, string memory p2, uint p3) internal view { 973 | _sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint)", p0, p1, p2, p3)); 974 | } 975 | 976 | function log(string memory p0, address p1, string memory p2, string memory p3) internal view { 977 | _sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3)); 978 | } 979 | 980 | function log(string memory p0, address p1, string memory p2, bool p3) internal view { 981 | _sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3)); 982 | } 983 | 984 | function log(string memory p0, address p1, string memory p2, address p3) internal view { 985 | _sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3)); 986 | } 987 | 988 | function log(string memory p0, address p1, bool p2, uint p3) internal view { 989 | _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint)", p0, p1, p2, p3)); 990 | } 991 | 992 | function log(string memory p0, address p1, bool p2, string memory p3) internal view { 993 | _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3)); 994 | } 995 | 996 | function log(string memory p0, address p1, bool p2, bool p3) internal view { 997 | _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3)); 998 | } 999 | 1000 | function log(string memory p0, address p1, bool p2, address p3) internal view { 1001 | _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3)); 1002 | } 1003 | 1004 | function log(string memory p0, address p1, address p2, uint p3) internal view { 1005 | _sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint)", p0, p1, p2, p3)); 1006 | } 1007 | 1008 | function log(string memory p0, address p1, address p2, string memory p3) internal view { 1009 | _sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3)); 1010 | } 1011 | 1012 | function log(string memory p0, address p1, address p2, bool p3) internal view { 1013 | _sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3)); 1014 | } 1015 | 1016 | function log(string memory p0, address p1, address p2, address p3) internal view { 1017 | _sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3)); 1018 | } 1019 | 1020 | function log(bool p0, uint p1, uint p2, uint p3) internal view { 1021 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,uint)", p0, p1, p2, p3)); 1022 | } 1023 | 1024 | function log(bool p0, uint p1, uint p2, string memory p3) internal view { 1025 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,string)", p0, p1, p2, p3)); 1026 | } 1027 | 1028 | function log(bool p0, uint p1, uint p2, bool p3) internal view { 1029 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,bool)", p0, p1, p2, p3)); 1030 | } 1031 | 1032 | function log(bool p0, uint p1, uint p2, address p3) internal view { 1033 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,address)", p0, p1, p2, p3)); 1034 | } 1035 | 1036 | function log(bool p0, uint p1, string memory p2, uint p3) internal view { 1037 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,uint)", p0, p1, p2, p3)); 1038 | } 1039 | 1040 | function log(bool p0, uint p1, string memory p2, string memory p3) internal view { 1041 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,string)", p0, p1, p2, p3)); 1042 | } 1043 | 1044 | function log(bool p0, uint p1, string memory p2, bool p3) internal view { 1045 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,bool)", p0, p1, p2, p3)); 1046 | } 1047 | 1048 | function log(bool p0, uint p1, string memory p2, address p3) internal view { 1049 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,address)", p0, p1, p2, p3)); 1050 | } 1051 | 1052 | function log(bool p0, uint p1, bool p2, uint p3) internal view { 1053 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,uint)", p0, p1, p2, p3)); 1054 | } 1055 | 1056 | function log(bool p0, uint p1, bool p2, string memory p3) internal view { 1057 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,string)", p0, p1, p2, p3)); 1058 | } 1059 | 1060 | function log(bool p0, uint p1, bool p2, bool p3) internal view { 1061 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,bool)", p0, p1, p2, p3)); 1062 | } 1063 | 1064 | function log(bool p0, uint p1, bool p2, address p3) internal view { 1065 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,address)", p0, p1, p2, p3)); 1066 | } 1067 | 1068 | function log(bool p0, uint p1, address p2, uint p3) internal view { 1069 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,uint)", p0, p1, p2, p3)); 1070 | } 1071 | 1072 | function log(bool p0, uint p1, address p2, string memory p3) internal view { 1073 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,string)", p0, p1, p2, p3)); 1074 | } 1075 | 1076 | function log(bool p0, uint p1, address p2, bool p3) internal view { 1077 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,bool)", p0, p1, p2, p3)); 1078 | } 1079 | 1080 | function log(bool p0, uint p1, address p2, address p3) internal view { 1081 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,address)", p0, p1, p2, p3)); 1082 | } 1083 | 1084 | function log(bool p0, string memory p1, uint p2, uint p3) internal view { 1085 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,uint)", p0, p1, p2, p3)); 1086 | } 1087 | 1088 | function log(bool p0, string memory p1, uint p2, string memory p3) internal view { 1089 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,string)", p0, p1, p2, p3)); 1090 | } 1091 | 1092 | function log(bool p0, string memory p1, uint p2, bool p3) internal view { 1093 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,bool)", p0, p1, p2, p3)); 1094 | } 1095 | 1096 | function log(bool p0, string memory p1, uint p2, address p3) internal view { 1097 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,address)", p0, p1, p2, p3)); 1098 | } 1099 | 1100 | function log(bool p0, string memory p1, string memory p2, uint p3) internal view { 1101 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint)", p0, p1, p2, p3)); 1102 | } 1103 | 1104 | function log(bool p0, string memory p1, string memory p2, string memory p3) internal view { 1105 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3)); 1106 | } 1107 | 1108 | function log(bool p0, string memory p1, string memory p2, bool p3) internal view { 1109 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3)); 1110 | } 1111 | 1112 | function log(bool p0, string memory p1, string memory p2, address p3) internal view { 1113 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3)); 1114 | } 1115 | 1116 | function log(bool p0, string memory p1, bool p2, uint p3) internal view { 1117 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint)", p0, p1, p2, p3)); 1118 | } 1119 | 1120 | function log(bool p0, string memory p1, bool p2, string memory p3) internal view { 1121 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3)); 1122 | } 1123 | 1124 | function log(bool p0, string memory p1, bool p2, bool p3) internal view { 1125 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3)); 1126 | } 1127 | 1128 | function log(bool p0, string memory p1, bool p2, address p3) internal view { 1129 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3)); 1130 | } 1131 | 1132 | function log(bool p0, string memory p1, address p2, uint p3) internal view { 1133 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint)", p0, p1, p2, p3)); 1134 | } 1135 | 1136 | function log(bool p0, string memory p1, address p2, string memory p3) internal view { 1137 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3)); 1138 | } 1139 | 1140 | function log(bool p0, string memory p1, address p2, bool p3) internal view { 1141 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3)); 1142 | } 1143 | 1144 | function log(bool p0, string memory p1, address p2, address p3) internal view { 1145 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3)); 1146 | } 1147 | 1148 | function log(bool p0, bool p1, uint p2, uint p3) internal view { 1149 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,uint)", p0, p1, p2, p3)); 1150 | } 1151 | 1152 | function log(bool p0, bool p1, uint p2, string memory p3) internal view { 1153 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,string)", p0, p1, p2, p3)); 1154 | } 1155 | 1156 | function log(bool p0, bool p1, uint p2, bool p3) internal view { 1157 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,bool)", p0, p1, p2, p3)); 1158 | } 1159 | 1160 | function log(bool p0, bool p1, uint p2, address p3) internal view { 1161 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,address)", p0, p1, p2, p3)); 1162 | } 1163 | 1164 | function log(bool p0, bool p1, string memory p2, uint p3) internal view { 1165 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint)", p0, p1, p2, p3)); 1166 | } 1167 | 1168 | function log(bool p0, bool p1, string memory p2, string memory p3) internal view { 1169 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3)); 1170 | } 1171 | 1172 | function log(bool p0, bool p1, string memory p2, bool p3) internal view { 1173 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3)); 1174 | } 1175 | 1176 | function log(bool p0, bool p1, string memory p2, address p3) internal view { 1177 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3)); 1178 | } 1179 | 1180 | function log(bool p0, bool p1, bool p2, uint p3) internal view { 1181 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint)", p0, p1, p2, p3)); 1182 | } 1183 | 1184 | function log(bool p0, bool p1, bool p2, string memory p3) internal view { 1185 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3)); 1186 | } 1187 | 1188 | function log(bool p0, bool p1, bool p2, bool p3) internal view { 1189 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3)); 1190 | } 1191 | 1192 | function log(bool p0, bool p1, bool p2, address p3) internal view { 1193 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3)); 1194 | } 1195 | 1196 | function log(bool p0, bool p1, address p2, uint p3) internal view { 1197 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint)", p0, p1, p2, p3)); 1198 | } 1199 | 1200 | function log(bool p0, bool p1, address p2, string memory p3) internal view { 1201 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3)); 1202 | } 1203 | 1204 | function log(bool p0, bool p1, address p2, bool p3) internal view { 1205 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3)); 1206 | } 1207 | 1208 | function log(bool p0, bool p1, address p2, address p3) internal view { 1209 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3)); 1210 | } 1211 | 1212 | function log(bool p0, address p1, uint p2, uint p3) internal view { 1213 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,uint)", p0, p1, p2, p3)); 1214 | } 1215 | 1216 | function log(bool p0, address p1, uint p2, string memory p3) internal view { 1217 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,string)", p0, p1, p2, p3)); 1218 | } 1219 | 1220 | function log(bool p0, address p1, uint p2, bool p3) internal view { 1221 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,bool)", p0, p1, p2, p3)); 1222 | } 1223 | 1224 | function log(bool p0, address p1, uint p2, address p3) internal view { 1225 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,address)", p0, p1, p2, p3)); 1226 | } 1227 | 1228 | function log(bool p0, address p1, string memory p2, uint p3) internal view { 1229 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint)", p0, p1, p2, p3)); 1230 | } 1231 | 1232 | function log(bool p0, address p1, string memory p2, string memory p3) internal view { 1233 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3)); 1234 | } 1235 | 1236 | function log(bool p0, address p1, string memory p2, bool p3) internal view { 1237 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3)); 1238 | } 1239 | 1240 | function log(bool p0, address p1, string memory p2, address p3) internal view { 1241 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3)); 1242 | } 1243 | 1244 | function log(bool p0, address p1, bool p2, uint p3) internal view { 1245 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint)", p0, p1, p2, p3)); 1246 | } 1247 | 1248 | function log(bool p0, address p1, bool p2, string memory p3) internal view { 1249 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3)); 1250 | } 1251 | 1252 | function log(bool p0, address p1, bool p2, bool p3) internal view { 1253 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3)); 1254 | } 1255 | 1256 | function log(bool p0, address p1, bool p2, address p3) internal view { 1257 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3)); 1258 | } 1259 | 1260 | function log(bool p0, address p1, address p2, uint p3) internal view { 1261 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint)", p0, p1, p2, p3)); 1262 | } 1263 | 1264 | function log(bool p0, address p1, address p2, string memory p3) internal view { 1265 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3)); 1266 | } 1267 | 1268 | function log(bool p0, address p1, address p2, bool p3) internal view { 1269 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3)); 1270 | } 1271 | 1272 | function log(bool p0, address p1, address p2, address p3) internal view { 1273 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3)); 1274 | } 1275 | 1276 | function log(address p0, uint p1, uint p2, uint p3) internal view { 1277 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,uint)", p0, p1, p2, p3)); 1278 | } 1279 | 1280 | function log(address p0, uint p1, uint p2, string memory p3) internal view { 1281 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,string)", p0, p1, p2, p3)); 1282 | } 1283 | 1284 | function log(address p0, uint p1, uint p2, bool p3) internal view { 1285 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,bool)", p0, p1, p2, p3)); 1286 | } 1287 | 1288 | function log(address p0, uint p1, uint p2, address p3) internal view { 1289 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,address)", p0, p1, p2, p3)); 1290 | } 1291 | 1292 | function log(address p0, uint p1, string memory p2, uint p3) internal view { 1293 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,uint)", p0, p1, p2, p3)); 1294 | } 1295 | 1296 | function log(address p0, uint p1, string memory p2, string memory p3) internal view { 1297 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,string)", p0, p1, p2, p3)); 1298 | } 1299 | 1300 | function log(address p0, uint p1, string memory p2, bool p3) internal view { 1301 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,bool)", p0, p1, p2, p3)); 1302 | } 1303 | 1304 | function log(address p0, uint p1, string memory p2, address p3) internal view { 1305 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,address)", p0, p1, p2, p3)); 1306 | } 1307 | 1308 | function log(address p0, uint p1, bool p2, uint p3) internal view { 1309 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,uint)", p0, p1, p2, p3)); 1310 | } 1311 | 1312 | function log(address p0, uint p1, bool p2, string memory p3) internal view { 1313 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,string)", p0, p1, p2, p3)); 1314 | } 1315 | 1316 | function log(address p0, uint p1, bool p2, bool p3) internal view { 1317 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,bool)", p0, p1, p2, p3)); 1318 | } 1319 | 1320 | function log(address p0, uint p1, bool p2, address p3) internal view { 1321 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,address)", p0, p1, p2, p3)); 1322 | } 1323 | 1324 | function log(address p0, uint p1, address p2, uint p3) internal view { 1325 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,uint)", p0, p1, p2, p3)); 1326 | } 1327 | 1328 | function log(address p0, uint p1, address p2, string memory p3) internal view { 1329 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,string)", p0, p1, p2, p3)); 1330 | } 1331 | 1332 | function log(address p0, uint p1, address p2, bool p3) internal view { 1333 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,bool)", p0, p1, p2, p3)); 1334 | } 1335 | 1336 | function log(address p0, uint p1, address p2, address p3) internal view { 1337 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,address)", p0, p1, p2, p3)); 1338 | } 1339 | 1340 | function log(address p0, string memory p1, uint p2, uint p3) internal view { 1341 | _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,uint)", p0, p1, p2, p3)); 1342 | } 1343 | 1344 | function log(address p0, string memory p1, uint p2, string memory p3) internal view { 1345 | _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,string)", p0, p1, p2, p3)); 1346 | } 1347 | 1348 | function log(address p0, string memory p1, uint p2, bool p3) internal view { 1349 | _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,bool)", p0, p1, p2, p3)); 1350 | } 1351 | 1352 | function log(address p0, string memory p1, uint p2, address p3) internal view { 1353 | _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,address)", p0, p1, p2, p3)); 1354 | } 1355 | 1356 | function log(address p0, string memory p1, string memory p2, uint p3) internal view { 1357 | _sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint)", p0, p1, p2, p3)); 1358 | } 1359 | 1360 | function log(address p0, string memory p1, string memory p2, string memory p3) internal view { 1361 | _sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3)); 1362 | } 1363 | 1364 | function log(address p0, string memory p1, string memory p2, bool p3) internal view { 1365 | _sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3)); 1366 | } 1367 | 1368 | function log(address p0, string memory p1, string memory p2, address p3) internal view { 1369 | _sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3)); 1370 | } 1371 | 1372 | function log(address p0, string memory p1, bool p2, uint p3) internal view { 1373 | _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint)", p0, p1, p2, p3)); 1374 | } 1375 | 1376 | function log(address p0, string memory p1, bool p2, string memory p3) internal view { 1377 | _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3)); 1378 | } 1379 | 1380 | function log(address p0, string memory p1, bool p2, bool p3) internal view { 1381 | _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3)); 1382 | } 1383 | 1384 | function log(address p0, string memory p1, bool p2, address p3) internal view { 1385 | _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3)); 1386 | } 1387 | 1388 | function log(address p0, string memory p1, address p2, uint p3) internal view { 1389 | _sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint)", p0, p1, p2, p3)); 1390 | } 1391 | 1392 | function log(address p0, string memory p1, address p2, string memory p3) internal view { 1393 | _sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3)); 1394 | } 1395 | 1396 | function log(address p0, string memory p1, address p2, bool p3) internal view { 1397 | _sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3)); 1398 | } 1399 | 1400 | function log(address p0, string memory p1, address p2, address p3) internal view { 1401 | _sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3)); 1402 | } 1403 | 1404 | function log(address p0, bool p1, uint p2, uint p3) internal view { 1405 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,uint)", p0, p1, p2, p3)); 1406 | } 1407 | 1408 | function log(address p0, bool p1, uint p2, string memory p3) internal view { 1409 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,string)", p0, p1, p2, p3)); 1410 | } 1411 | 1412 | function log(address p0, bool p1, uint p2, bool p3) internal view { 1413 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,bool)", p0, p1, p2, p3)); 1414 | } 1415 | 1416 | function log(address p0, bool p1, uint p2, address p3) internal view { 1417 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,address)", p0, p1, p2, p3)); 1418 | } 1419 | 1420 | function log(address p0, bool p1, string memory p2, uint p3) internal view { 1421 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint)", p0, p1, p2, p3)); 1422 | } 1423 | 1424 | function log(address p0, bool p1, string memory p2, string memory p3) internal view { 1425 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3)); 1426 | } 1427 | 1428 | function log(address p0, bool p1, string memory p2, bool p3) internal view { 1429 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3)); 1430 | } 1431 | 1432 | function log(address p0, bool p1, string memory p2, address p3) internal view { 1433 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3)); 1434 | } 1435 | 1436 | function log(address p0, bool p1, bool p2, uint p3) internal view { 1437 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint)", p0, p1, p2, p3)); 1438 | } 1439 | 1440 | function log(address p0, bool p1, bool p2, string memory p3) internal view { 1441 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3)); 1442 | } 1443 | 1444 | function log(address p0, bool p1, bool p2, bool p3) internal view { 1445 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3)); 1446 | } 1447 | 1448 | function log(address p0, bool p1, bool p2, address p3) internal view { 1449 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3)); 1450 | } 1451 | 1452 | function log(address p0, bool p1, address p2, uint p3) internal view { 1453 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint)", p0, p1, p2, p3)); 1454 | } 1455 | 1456 | function log(address p0, bool p1, address p2, string memory p3) internal view { 1457 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3)); 1458 | } 1459 | 1460 | function log(address p0, bool p1, address p2, bool p3) internal view { 1461 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3)); 1462 | } 1463 | 1464 | function log(address p0, bool p1, address p2, address p3) internal view { 1465 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3)); 1466 | } 1467 | 1468 | function log(address p0, address p1, uint p2, uint p3) internal view { 1469 | _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,uint)", p0, p1, p2, p3)); 1470 | } 1471 | 1472 | function log(address p0, address p1, uint p2, string memory p3) internal view { 1473 | _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,string)", p0, p1, p2, p3)); 1474 | } 1475 | 1476 | function log(address p0, address p1, uint p2, bool p3) internal view { 1477 | _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,bool)", p0, p1, p2, p3)); 1478 | } 1479 | 1480 | function log(address p0, address p1, uint p2, address p3) internal view { 1481 | _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,address)", p0, p1, p2, p3)); 1482 | } 1483 | 1484 | function log(address p0, address p1, string memory p2, uint p3) internal view { 1485 | _sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint)", p0, p1, p2, p3)); 1486 | } 1487 | 1488 | function log(address p0, address p1, string memory p2, string memory p3) internal view { 1489 | _sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3)); 1490 | } 1491 | 1492 | function log(address p0, address p1, string memory p2, bool p3) internal view { 1493 | _sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3)); 1494 | } 1495 | 1496 | function log(address p0, address p1, string memory p2, address p3) internal view { 1497 | _sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3)); 1498 | } 1499 | 1500 | function log(address p0, address p1, bool p2, uint p3) internal view { 1501 | _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint)", p0, p1, p2, p3)); 1502 | } 1503 | 1504 | function log(address p0, address p1, bool p2, string memory p3) internal view { 1505 | _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3)); 1506 | } 1507 | 1508 | function log(address p0, address p1, bool p2, bool p3) internal view { 1509 | _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3)); 1510 | } 1511 | 1512 | function log(address p0, address p1, bool p2, address p3) internal view { 1513 | _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3)); 1514 | } 1515 | 1516 | function log(address p0, address p1, address p2, uint p3) internal view { 1517 | _sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint)", p0, p1, p2, p3)); 1518 | } 1519 | 1520 | function log(address p0, address p1, address p2, string memory p3) internal view { 1521 | _sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3)); 1522 | } 1523 | 1524 | function log(address p0, address p1, address p2, bool p3) internal view { 1525 | _sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3)); 1526 | } 1527 | 1528 | function log(address p0, address p1, address p2, address p3) internal view { 1529 | _sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3)); 1530 | } 1531 | 1532 | } --------------------------------------------------------------------------------