Commit e581966e authored by Mark Tyneway's avatar Mark Tyneway Committed by GitHub

contracts-bedrock: tightly pack creation timestamp (#6020)

Pack the creation timestamp in the storage slot along
with the address of the dispute games so that the
information can be accessed easily by services that
query the contract.

A service looking for recent dispute games can
binary search or linear search backwards using the
`gameAtIndex` function. It is guaranteed that the
timestamp will always increase or be equal as the
index increases.
parent 6742d0fe
...@@ -30,8 +30,8 @@ var ( ...@@ -30,8 +30,8 @@ var (
// DisputeGameFactoryMetaData contains all meta data concerning the DisputeGameFactory contract. // DisputeGameFactoryMetaData contains all meta data concerning the DisputeGameFactory contract.
var DisputeGameFactoryMetaData = &bind.MetaData{ var DisputeGameFactoryMetaData = &bind.MetaData{
ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"Hash\",\"name\":\"uuid\",\"type\":\"bytes32\"}],\"name\":\"GameAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"GameType\",\"name\":\"gameType\",\"type\":\"uint8\"}],\"name\":\"NoImplementation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"disputeProxy\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"GameType\",\"name\":\"gameType\",\"type\":\"uint8\"},{\"indexed\":true,\"internalType\":\"Claim\",\"name\":\"rootClaim\",\"type\":\"bytes32\"}],\"name\":\"DisputeGameCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"impl\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"GameType\",\"name\":\"gameType\",\"type\":\"uint8\"}],\"name\":\"ImplementationSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"GameType\",\"name\":\"gameType\",\"type\":\"uint8\"},{\"internalType\":\"Claim\",\"name\":\"rootClaim\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"create\",\"outputs\":[{\"internalType\":\"contractIDisputeGame\",\"name\":\"proxy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"disputeGameList\",\"outputs\":[{\"internalType\":\"contractIDisputeGame\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gameCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"_gameCount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"GameType\",\"name\":\"\",\"type\":\"uint8\"}],\"name\":\"gameImpls\",\"outputs\":[{\"internalType\":\"contractIDisputeGame\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"GameType\",\"name\":\"gameType\",\"type\":\"uint8\"},{\"internalType\":\"Claim\",\"name\":\"rootClaim\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"games\",\"outputs\":[{\"internalType\":\"contractIDisputeGame\",\"name\":\"_proxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"GameType\",\"name\":\"gameType\",\"type\":\"uint8\"},{\"internalType\":\"Claim\",\"name\":\"rootClaim\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"getGameUUID\",\"outputs\":[{\"internalType\":\"Hash\",\"name\":\"_uuid\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"GameType\",\"name\":\"gameType\",\"type\":\"uint8\"},{\"internalType\":\"contractIDisputeGame\",\"name\":\"impl\",\"type\":\"address\"}],\"name\":\"setImplementation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"Hash\",\"name\":\"uuid\",\"type\":\"bytes32\"}],\"name\":\"GameAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"GameType\",\"name\":\"gameType\",\"type\":\"uint8\"}],\"name\":\"NoImplementation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"disputeProxy\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"GameType\",\"name\":\"gameType\",\"type\":\"uint8\"},{\"indexed\":true,\"internalType\":\"Claim\",\"name\":\"rootClaim\",\"type\":\"bytes32\"}],\"name\":\"DisputeGameCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"impl\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"GameType\",\"name\":\"gameType\",\"type\":\"uint8\"}],\"name\":\"ImplementationSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"GameType\",\"name\":\"gameType\",\"type\":\"uint8\"},{\"internalType\":\"Claim\",\"name\":\"rootClaim\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"create\",\"outputs\":[{\"internalType\":\"contractIDisputeGame\",\"name\":\"proxy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_index\",\"type\":\"uint256\"}],\"name\":\"gameAtIndex\",\"outputs\":[{\"internalType\":\"contractIDisputeGame\",\"name\":\"proxy_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp_\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gameCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"gameCount_\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"GameType\",\"name\":\"\",\"type\":\"uint8\"}],\"name\":\"gameImpls\",\"outputs\":[{\"internalType\":\"contractIDisputeGame\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"GameType\",\"name\":\"_gameType\",\"type\":\"uint8\"},{\"internalType\":\"Claim\",\"name\":\"_rootClaim\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"games\",\"outputs\":[{\"internalType\":\"contractIDisputeGame\",\"name\":\"proxy_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp_\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"GameType\",\"name\":\"gameType\",\"type\":\"uint8\"},{\"internalType\":\"Claim\",\"name\":\"rootClaim\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"getGameUUID\",\"outputs\":[{\"internalType\":\"Hash\",\"name\":\"_uuid\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"GameType\",\"name\":\"gameType\",\"type\":\"uint8\"},{\"internalType\":\"contractIDisputeGame\",\"name\":\"impl\",\"type\":\"address\"}],\"name\":\"setImplementation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]",
Bin: "0x60806040523480156200001157600080fd5b506200001e600062000024565b62000292565b600054610100900460ff1615808015620000455750600054600160ff909116105b8062000075575062000062306200016260201b620008f81760201c565b15801562000075575060005460ff166001145b620000de5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000102576000805461ff0019166101001790555b6200010c62000171565b6200011782620001d9565b80156200015e576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054610100900460ff16620001cd5760405162461bcd60e51b815260206004820152602b60248201526000805160206200121c83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000d5565b620001d76200022b565b565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16620002875760405162461bcd60e51b815260206004820152602b60248201526000805160206200121c83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000d5565b620001d733620001d9565b610f7a80620002a26000396000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c8063763014a611610081578063c4d66de81161005b578063c4d66de81461026b578063dfa162d31461027e578063f2fde38b146102b457600080fd5b8063763014a6146102275780638da5cb5b1461023a578063c49d52711461025857600080fd5b80634d1975b4116100b25780634d1975b4146101d857806354fd4d50146101e0578063715018a61461021f57600080fd5b806326daafbe146100d95780633142e55e1461018b57806345583b7a146101c3575b600080fd5b6101786100e7366004610cbf565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0810180517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0830180517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08086018051988652968352606087529451609f0190941683209190925291905291905290565b6040519081526020015b60405180910390f35b61019e610199366004610da8565b6102c7565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610182565b6101d66101d1366004610e51565b61055c565b005b606754610178565b604080518082018252600581527f302e302e31000000000000000000000000000000000000000000000000000000602082015290516101829190610e88565b6101d66105e3565b61019e610235366004610efb565b6105f7565b60335473ffffffffffffffffffffffffffffffffffffffff1661019e565b61019e610266366004610da8565b61062e565b6101d6610279366004610f14565b6106a5565b61019e61028c366004610f38565b60656020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6101d66102c2366004610f14565b610841565b60ff841660009081526065602052604081205473ffffffffffffffffffffffffffffffffffffffff1680610331576040517f44265d6f00000000000000000000000000000000000000000000000000000000815260ff871660048201526024015b60405180910390fd5b61039485858560405160200161034993929190610f53565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905273ffffffffffffffffffffffffffffffffffffffff831690610914565b91508173ffffffffffffffffffffffffffffffffffffffff16638129fc1c6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156103de57600080fd5b505af11580156103f2573d6000803e3d6000fd5b505050506000610439878787878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506100e792505050565b60008181526066602052604090205490915073ffffffffffffffffffffffffffffffffffffffff161561049b576040517f014f6fe500000000000000000000000000000000000000000000000000000000815260048101829052602401610328565b600081815260666020526040808220805473ffffffffffffffffffffffffffffffffffffffff87167fffffffffffffffffffffffff00000000000000000000000000000000000000009182168117909255606780546001810182559085527f9787eeb91fe3101235e4a76063c7023ecb40f923f97916639c598592fa30d6ae018054909116821790559051889260ff8b1692917ffad0599ff449d8d9685eadecca8cb9e00924c5fd8367c1c09469824939e1ffec9190a45050949350505050565b610564610a48565b60ff821660008181526065602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8616908117909155905190917f623713f72f6e427a8044bb8b3bd6834357cf285decbaa21bcc73c1d0632c4d8491a35050565b6105eb610a48565b6105f56000610ac9565b565b6067818154811061060757600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b600060666000610675878787878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506100e792505050565b815260208101919091526040016000205473ffffffffffffffffffffffffffffffffffffffff1695945050505050565b600054610100900460ff16158080156106c55750600054600160ff909116105b806106df5750303b1580156106df575060005460ff166001145b61076b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610328565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156107c957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6107d1610b40565b6107da82610ac9565b801561083d57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b610849610a48565b73ffffffffffffffffffffffffffffffffffffffff81166108ec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610328565b6108f581610ac9565b50565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60006002825101603f8101600a81036040518360581b8260e81b177f6100003d81600a3d39f3363d3d373d3d3d3d610000806035363936013d7300001781528660601b601e8201527f5af43d3d93803e603357fd5bf300000000000000000000000000000000000000603282015285519150603f8101602087015b602084106109cc57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909301926020918201910161098f565b517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602085900360031b1b16815260f085901b9083015282816000f0945084610a39577febfef1880000000000000000000000000000000000000000000000000000000060005260206000fd5b90910160405250909392505050565b60335473ffffffffffffffffffffffffffffffffffffffff1633146105f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610328565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610bd7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610328565b6105f5600054610100900460ff16610c71576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610328565b6105f533610ac9565b803560ff81168114610c8b57600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060608486031215610cd457600080fd5b610cdd84610c7a565b925060208401359150604084013567ffffffffffffffff80821115610d0157600080fd5b818601915086601f830112610d1557600080fd5b813581811115610d2757610d27610c90565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715610d6d57610d6d610c90565b81604052828152896020848701011115610d8657600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b60008060008060608587031215610dbe57600080fd5b610dc785610c7a565b935060208501359250604085013567ffffffffffffffff80821115610deb57600080fd5b818701915087601f830112610dff57600080fd5b813581811115610e0e57600080fd5b886020828501011115610e2057600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff811681146108f557600080fd5b60008060408385031215610e6457600080fd5b610e6d83610c7a565b91506020830135610e7d81610e2f565b809150509250929050565b600060208083528351808285015260005b81811015610eb557858101830151858201604001528201610e99565b81811115610ec7576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b600060208284031215610f0d57600080fd5b5035919050565b600060208284031215610f2657600080fd5b8135610f3181610e2f565b9392505050565b600060208284031215610f4a57600080fd5b610f3182610c7a565b83815281836020830137600091016020019081529291505056fea164736f6c634300080f000a496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069", Bin: "0x60806040523480156200001157600080fd5b506200001e600062000024565b62000292565b600054610100900460ff1615808015620000455750600054600160ff909116105b8062000075575062000062306200016260201b620009051760201c565b15801562000075575060005460ff166001145b620000de5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000102576000805461ff0019166101001790555b6200010c62000171565b6200011782620001d9565b80156200015e576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054610100900460ff16620001cd5760405162461bcd60e51b815260206004820152602b60248201526000805160206200125883398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000d5565b620001d76200022b565b565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16620002875760405162461bcd60e51b815260206004820152602b60248201526000805160206200125883398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000d5565b620001d733620001d9565b610fb680620002a26000396000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c80638da5cb5b11610081578063c4d66de81161005b578063c4d66de814610297578063dfa162d3146102aa578063f2fde38b146102e057600080fd5b80638da5cb5b14610227578063bb8aa1fc14610245578063c49d52711461028457600080fd5b80634d1975b4116100b25780634d1975b4146101d857806354fd4d50146101e0578063715018a61461021f57600080fd5b806326daafbe146100d95780633142e55e1461018b57806345583b7a146101c3575b600080fd5b6101786100e7366004610ccc565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0810180517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0830180517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08086018051988652968352606087529451609f0190941683209190925291905291905290565b6040519081526020015b60405180910390f35b61019e610199366004610db5565b6102f3565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610182565b6101d66101d1366004610e5e565b61054f565b005b606754610178565b604080518082018252600581527f302e302e32000000000000000000000000000000000000000000000000000000602082015290516101829190610e95565b6101d66105d6565b60335473ffffffffffffffffffffffffffffffffffffffff1661019e565b610258610253366004610f08565b6105ea565b6040805173ffffffffffffffffffffffffffffffffffffffff9093168352602083019190915201610182565b610258610292366004610db5565b610634565b6101d66102a5366004610f21565b6106b2565b61019e6102b8366004610f45565b60656020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6101d66102ee366004610f21565b61084e565b60ff841660009081526065602052604081205473ffffffffffffffffffffffffffffffffffffffff168061035d576040517f44265d6f00000000000000000000000000000000000000000000000000000000815260ff871660048201526024015b60405180910390fd5b6103c085858560405160200161037593929190610f60565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905273ffffffffffffffffffffffffffffffffffffffff831690610921565b91508173ffffffffffffffffffffffffffffffffffffffff16638129fc1c6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561040a57600080fd5b505af115801561041e573d6000803e3d6000fd5b505050506000610465878787878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506100e792505050565b600081815260666020526040902054909150156104b1576040517f014f6fe500000000000000000000000000000000000000000000000000000000815260048101829052602401610354565b60004260a01b8417600083815260666020526040808220839055606780546001810182559083527f9787eeb91fe3101235e4a76063c7023ecb40f923f97916639c598592fa30d6ae0183905551919250889160ff8b169173ffffffffffffffffffffffffffffffffffffffff8816917ffad0599ff449d8d9685eadecca8cb9e00924c5fd8367c1c09469824939e1ffec9190a4505050949350505050565b610557610a55565b60ff821660008181526065602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8616908117909155905190917f623713f72f6e427a8044bb8b3bd6834357cf285decbaa21bcc73c1d0632c4d8491a35050565b6105de610a55565b6105e86000610ad6565b565b60008060006067848154811061060257610602610f7a565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff81169560a09190911c945092505050565b600080600061067a878787878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506100e792505050565b60009081526066602052604090205473ffffffffffffffffffffffffffffffffffffffff81169860a09190911c975095505050505050565b600054610100900460ff16158080156106d25750600054600160ff909116105b806106ec5750303b1580156106ec575060005460ff166001145b610778576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610354565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156107d657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6107de610b4d565b6107e782610ad6565b801561084a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b610856610a55565b73ffffffffffffffffffffffffffffffffffffffff81166108f9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610354565b61090281610ad6565b50565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60006002825101603f8101600a81036040518360581b8260e81b177f6100003d81600a3d39f3363d3d373d3d3d3d610000806035363936013d7300001781528660601b601e8201527f5af43d3d93803e603357fd5bf300000000000000000000000000000000000000603282015285519150603f8101602087015b602084106109d957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909301926020918201910161099c565b517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602085900360031b1b16815260f085901b9083015282816000f0945084610a46577febfef1880000000000000000000000000000000000000000000000000000000060005260206000fd5b90910160405250909392505050565b60335473ffffffffffffffffffffffffffffffffffffffff1633146105e8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610354565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610be4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610354565b6105e8600054610100900460ff16610c7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610354565b6105e833610ad6565b803560ff81168114610c9857600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060608486031215610ce157600080fd5b610cea84610c87565b925060208401359150604084013567ffffffffffffffff80821115610d0e57600080fd5b818601915086601f830112610d2257600080fd5b813581811115610d3457610d34610c9d565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715610d7a57610d7a610c9d565b81604052828152896020848701011115610d9357600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b60008060008060608587031215610dcb57600080fd5b610dd485610c87565b935060208501359250604085013567ffffffffffffffff80821115610df857600080fd5b818701915087601f830112610e0c57600080fd5b813581811115610e1b57600080fd5b886020828501011115610e2d57600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461090257600080fd5b60008060408385031215610e7157600080fd5b610e7a83610c87565b91506020830135610e8a81610e3c565b809150509250929050565b600060208083528351808285015260005b81811015610ec257858101830151858201604001528201610ea6565b81811115610ed4576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b600060208284031215610f1a57600080fd5b5035919050565b600060208284031215610f3357600080fd5b8135610f3e81610e3c565b9392505050565b600060208284031215610f5757600080fd5b610f3e82610c87565b838152818360208301376000910160200190815292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069",
} }
// DisputeGameFactoryABI is the input ABI used to generate the binding from. // DisputeGameFactoryABI is the input ABI used to generate the binding from.
...@@ -201,40 +201,54 @@ func (_DisputeGameFactory *DisputeGameFactoryTransactorRaw) Transact(opts *bind. ...@@ -201,40 +201,54 @@ func (_DisputeGameFactory *DisputeGameFactoryTransactorRaw) Transact(opts *bind.
return _DisputeGameFactory.Contract.contract.Transact(opts, method, params...) return _DisputeGameFactory.Contract.contract.Transact(opts, method, params...)
} }
// DisputeGameList is a free data retrieval call binding the contract method 0x763014a6. // GameAtIndex is a free data retrieval call binding the contract method 0xbb8aa1fc.
// //
// Solidity: function disputeGameList(uint256 ) view returns(address) // Solidity: function gameAtIndex(uint256 _index) view returns(address proxy_, uint256 timestamp_)
func (_DisputeGameFactory *DisputeGameFactoryCaller) DisputeGameList(opts *bind.CallOpts, arg0 *big.Int) (common.Address, error) { func (_DisputeGameFactory *DisputeGameFactoryCaller) GameAtIndex(opts *bind.CallOpts, _index *big.Int) (struct {
Proxy common.Address
Timestamp *big.Int
}, error) {
var out []interface{} var out []interface{}
err := _DisputeGameFactory.contract.Call(opts, &out, "disputeGameList", arg0) err := _DisputeGameFactory.contract.Call(opts, &out, "gameAtIndex", _index)
outstruct := new(struct {
Proxy common.Address
Timestamp *big.Int
})
if err != nil { if err != nil {
return *new(common.Address), err return *outstruct, err
} }
out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) outstruct.Proxy = *abi.ConvertType(out[0], new(common.Address)).(*common.Address)
outstruct.Timestamp = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int)
return out0, err return *outstruct, err
} }
// DisputeGameList is a free data retrieval call binding the contract method 0x763014a6. // GameAtIndex is a free data retrieval call binding the contract method 0xbb8aa1fc.
// //
// Solidity: function disputeGameList(uint256 ) view returns(address) // Solidity: function gameAtIndex(uint256 _index) view returns(address proxy_, uint256 timestamp_)
func (_DisputeGameFactory *DisputeGameFactorySession) DisputeGameList(arg0 *big.Int) (common.Address, error) { func (_DisputeGameFactory *DisputeGameFactorySession) GameAtIndex(_index *big.Int) (struct {
return _DisputeGameFactory.Contract.DisputeGameList(&_DisputeGameFactory.CallOpts, arg0) Proxy common.Address
Timestamp *big.Int
}, error) {
return _DisputeGameFactory.Contract.GameAtIndex(&_DisputeGameFactory.CallOpts, _index)
} }
// DisputeGameList is a free data retrieval call binding the contract method 0x763014a6. // GameAtIndex is a free data retrieval call binding the contract method 0xbb8aa1fc.
// //
// Solidity: function disputeGameList(uint256 ) view returns(address) // Solidity: function gameAtIndex(uint256 _index) view returns(address proxy_, uint256 timestamp_)
func (_DisputeGameFactory *DisputeGameFactoryCallerSession) DisputeGameList(arg0 *big.Int) (common.Address, error) { func (_DisputeGameFactory *DisputeGameFactoryCallerSession) GameAtIndex(_index *big.Int) (struct {
return _DisputeGameFactory.Contract.DisputeGameList(&_DisputeGameFactory.CallOpts, arg0) Proxy common.Address
Timestamp *big.Int
}, error) {
return _DisputeGameFactory.Contract.GameAtIndex(&_DisputeGameFactory.CallOpts, _index)
} }
// GameCount is a free data retrieval call binding the contract method 0x4d1975b4. // GameCount is a free data retrieval call binding the contract method 0x4d1975b4.
// //
// Solidity: function gameCount() view returns(uint256 _gameCount) // Solidity: function gameCount() view returns(uint256 gameCount_)
func (_DisputeGameFactory *DisputeGameFactoryCaller) GameCount(opts *bind.CallOpts) (*big.Int, error) { func (_DisputeGameFactory *DisputeGameFactoryCaller) GameCount(opts *bind.CallOpts) (*big.Int, error) {
var out []interface{} var out []interface{}
err := _DisputeGameFactory.contract.Call(opts, &out, "gameCount") err := _DisputeGameFactory.contract.Call(opts, &out, "gameCount")
...@@ -251,14 +265,14 @@ func (_DisputeGameFactory *DisputeGameFactoryCaller) GameCount(opts *bind.CallOp ...@@ -251,14 +265,14 @@ func (_DisputeGameFactory *DisputeGameFactoryCaller) GameCount(opts *bind.CallOp
// GameCount is a free data retrieval call binding the contract method 0x4d1975b4. // GameCount is a free data retrieval call binding the contract method 0x4d1975b4.
// //
// Solidity: function gameCount() view returns(uint256 _gameCount) // Solidity: function gameCount() view returns(uint256 gameCount_)
func (_DisputeGameFactory *DisputeGameFactorySession) GameCount() (*big.Int, error) { func (_DisputeGameFactory *DisputeGameFactorySession) GameCount() (*big.Int, error) {
return _DisputeGameFactory.Contract.GameCount(&_DisputeGameFactory.CallOpts) return _DisputeGameFactory.Contract.GameCount(&_DisputeGameFactory.CallOpts)
} }
// GameCount is a free data retrieval call binding the contract method 0x4d1975b4. // GameCount is a free data retrieval call binding the contract method 0x4d1975b4.
// //
// Solidity: function gameCount() view returns(uint256 _gameCount) // Solidity: function gameCount() view returns(uint256 gameCount_)
func (_DisputeGameFactory *DisputeGameFactoryCallerSession) GameCount() (*big.Int, error) { func (_DisputeGameFactory *DisputeGameFactoryCallerSession) GameCount() (*big.Int, error) {
return _DisputeGameFactory.Contract.GameCount(&_DisputeGameFactory.CallOpts) return _DisputeGameFactory.Contract.GameCount(&_DisputeGameFactory.CallOpts)
} }
...@@ -296,33 +310,47 @@ func (_DisputeGameFactory *DisputeGameFactoryCallerSession) GameImpls(arg0 uint8 ...@@ -296,33 +310,47 @@ func (_DisputeGameFactory *DisputeGameFactoryCallerSession) GameImpls(arg0 uint8
// Games is a free data retrieval call binding the contract method 0xc49d5271. // Games is a free data retrieval call binding the contract method 0xc49d5271.
// //
// Solidity: function games(uint8 gameType, bytes32 rootClaim, bytes extraData) view returns(address _proxy) // Solidity: function games(uint8 _gameType, bytes32 _rootClaim, bytes _extraData) view returns(address proxy_, uint256 timestamp_)
func (_DisputeGameFactory *DisputeGameFactoryCaller) Games(opts *bind.CallOpts, gameType uint8, rootClaim [32]byte, extraData []byte) (common.Address, error) { func (_DisputeGameFactory *DisputeGameFactoryCaller) Games(opts *bind.CallOpts, _gameType uint8, _rootClaim [32]byte, _extraData []byte) (struct {
Proxy common.Address
Timestamp *big.Int
}, error) {
var out []interface{} var out []interface{}
err := _DisputeGameFactory.contract.Call(opts, &out, "games", gameType, rootClaim, extraData) err := _DisputeGameFactory.contract.Call(opts, &out, "games", _gameType, _rootClaim, _extraData)
outstruct := new(struct {
Proxy common.Address
Timestamp *big.Int
})
if err != nil { if err != nil {
return *new(common.Address), err return *outstruct, err
} }
out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) outstruct.Proxy = *abi.ConvertType(out[0], new(common.Address)).(*common.Address)
outstruct.Timestamp = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int)
return out0, err return *outstruct, err
} }
// Games is a free data retrieval call binding the contract method 0xc49d5271. // Games is a free data retrieval call binding the contract method 0xc49d5271.
// //
// Solidity: function games(uint8 gameType, bytes32 rootClaim, bytes extraData) view returns(address _proxy) // Solidity: function games(uint8 _gameType, bytes32 _rootClaim, bytes _extraData) view returns(address proxy_, uint256 timestamp_)
func (_DisputeGameFactory *DisputeGameFactorySession) Games(gameType uint8, rootClaim [32]byte, extraData []byte) (common.Address, error) { func (_DisputeGameFactory *DisputeGameFactorySession) Games(_gameType uint8, _rootClaim [32]byte, _extraData []byte) (struct {
return _DisputeGameFactory.Contract.Games(&_DisputeGameFactory.CallOpts, gameType, rootClaim, extraData) Proxy common.Address
Timestamp *big.Int
}, error) {
return _DisputeGameFactory.Contract.Games(&_DisputeGameFactory.CallOpts, _gameType, _rootClaim, _extraData)
} }
// Games is a free data retrieval call binding the contract method 0xc49d5271. // Games is a free data retrieval call binding the contract method 0xc49d5271.
// //
// Solidity: function games(uint8 gameType, bytes32 rootClaim, bytes extraData) view returns(address _proxy) // Solidity: function games(uint8 _gameType, bytes32 _rootClaim, bytes _extraData) view returns(address proxy_, uint256 timestamp_)
func (_DisputeGameFactory *DisputeGameFactoryCallerSession) Games(gameType uint8, rootClaim [32]byte, extraData []byte) (common.Address, error) { func (_DisputeGameFactory *DisputeGameFactoryCallerSession) Games(_gameType uint8, _rootClaim [32]byte, _extraData []byte) (struct {
return _DisputeGameFactory.Contract.Games(&_DisputeGameFactory.CallOpts, gameType, rootClaim, extraData) Proxy common.Address
Timestamp *big.Int
}, error) {
return _DisputeGameFactory.Contract.Games(&_DisputeGameFactory.CallOpts, _gameType, _rootClaim, _extraData)
} }
// GetGameUUID is a free data retrieval call binding the contract method 0x26daafbe. // GetGameUUID is a free data retrieval call binding the contract method 0x26daafbe.
......
...@@ -27,11 +27,11 @@ CrossDomainOwnable_Test:test_onlyOwner_notOwner_reverts() (gas: 10597) ...@@ -27,11 +27,11 @@ CrossDomainOwnable_Test:test_onlyOwner_notOwner_reverts() (gas: 10597)
CrossDomainOwnable_Test:test_onlyOwner_succeeds() (gas: 34883) CrossDomainOwnable_Test:test_onlyOwner_succeeds() (gas: 34883)
DeployerWhitelist_Test:test_owner_succeeds() (gas: 7582) DeployerWhitelist_Test:test_owner_succeeds() (gas: 7582)
DeployerWhitelist_Test:test_storageSlots_succeeds() (gas: 33395) DeployerWhitelist_Test:test_storageSlots_succeeds() (gas: 33395)
DisputeGameFactory_Test:test_owner_succeeds() (gas: 12610) DisputeGameFactory_Owner_Test:test_owner_succeeds() (gas: 12559)
DisputeGameFactory_Test:test_setImplementation_notOwner_reverts() (gas: 16099) DisputeGameFactory_SetImplementation_Test:test_setImplementation_notOwner_reverts() (gas: 16042)
DisputeGameFactory_Test:test_setImplementation_succeeds() (gas: 44302) DisputeGameFactory_SetImplementation_Test:test_setImplementation_succeeds() (gas: 44243)
DisputeGameFactory_Test:test_transferOwnership_notOwner_reverts() (gas: 15974) DisputeGameFactory_TransferOwnership_Test:test_transferOwnership_notOwner_reverts() (gas: 15950)
DisputeGameFactory_Test:test_transferOwnership_succeeds() (gas: 18694) DisputeGameFactory_TransferOwnership_Test:test_transferOwnership_succeeds() (gas: 18642)
FaultDisputeGame_Test:test_clockTimeExceeded_reverts() (gas: 26413) FaultDisputeGame_Test:test_clockTimeExceeded_reverts() (gas: 26413)
FaultDisputeGame_Test:test_defendRoot_reverts() (gas: 13258) FaultDisputeGame_Test:test_defendRoot_reverts() (gas: 13258)
FaultDisputeGame_Test:test_duplicateClaim_reverts() (gas: 103259) FaultDisputeGame_Test:test_duplicateClaim_reverts() (gas: 103259)
......
...@@ -253,13 +253,13 @@ ...@@ -253,13 +253,13 @@
➡ contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory ➡ contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory
======================= =======================
| Name | Type | Slot | Offset | Bytes | Contract | | Name | Type | Slot | Offset | Bytes | Contract |
|-----------------|--------------------------------------------|------|--------|-------|-------------------------------------------------------------| |------------------|--------------------------------------------|------|--------|-------|-------------------------------------------------------------|
| _initialized | uint8 | 0 | 0 | 1 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory | | _initialized | uint8 | 0 | 0 | 1 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory |
| _initializing | bool | 0 | 1 | 1 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory | | _initializing | bool | 0 | 1 | 1 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory |
| __gap | uint256[50] | 1 | 0 | 1600 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory | | __gap | uint256[50] | 1 | 0 | 1600 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory |
| _owner | address | 51 | 0 | 20 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory | | _owner | address | 51 | 0 | 20 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory |
| __gap | uint256[49] | 52 | 0 | 1568 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory | | __gap | uint256[49] | 52 | 0 | 1568 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory |
| gameImpls | mapping(GameType => contract IDisputeGame) | 101 | 0 | 32 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory | | gameImpls | mapping(GameType => contract IDisputeGame) | 101 | 0 | 32 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory |
| disputeGames | mapping(Hash => contract IDisputeGame) | 102 | 0 | 32 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory | | _disputeGames | mapping(Hash => GameId) | 102 | 0 | 32 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory |
| disputeGameList | contract IDisputeGame[] | 103 | 0 | 32 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory | | _disputeGameList | GameId[] | 103 | 0 | 32 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory |
...@@ -15,7 +15,11 @@ import { IVersioned } from "./interfaces/IVersioned.sol"; ...@@ -15,7 +15,11 @@ import { IVersioned } from "./interfaces/IVersioned.sol";
/** /**
* @title DisputeGameFactory * @title DisputeGameFactory
* @notice A factory contract for creating `IDisputeGame` contracts. * @notice A factory contract for creating `IDisputeGame` contracts. All created dispute games
* are stored in both a mapping and an append only array. The timestamp of the creation
* time of the dispute game is packed tightly into the storage slot with the address of
* the dispute game. This is to make offchain discoverability of playable dispute games
* easier.
*/ */
contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, IVersioned { contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, IVersioned {
/** /**
...@@ -29,18 +33,18 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, IVersion ...@@ -29,18 +33,18 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, IVersion
mapping(GameType => IDisputeGame) public gameImpls; mapping(GameType => IDisputeGame) public gameImpls;
/** /**
* @notice Mapping of a hash of `gameType . rootClaim . extraData` to * @notice Mapping of a hash of `gameType || rootClaim || extraData` to
* the deployed `IDisputeGame` clone. * the deployed `IDisputeGame` clone.
* @dev Note: `.` denotes concatenation. * @dev Note: `||` denotes concatenation.
*/ */
mapping(Hash => IDisputeGame) internal disputeGames; mapping(Hash => GameId) internal _disputeGames;
/** /**
* @notice An append-only array of disputeGames that have been created. * @notice An append-only array of disputeGames that have been created.
* @dev This accessor is used by offchain game solvers to efficiently * @dev This accessor is used by offchain game solvers to efficiently
* track dispute games * track dispute games
*/ */
IDisputeGame[] public disputeGameList; GameId[] internal _disputeGameList;
/** /**
* @notice Constructs a new DisputeGameFactory contract. * @notice Constructs a new DisputeGameFactory contract.
...@@ -60,27 +64,46 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, IVersion ...@@ -60,27 +64,46 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, IVersion
/** /**
* @inheritdoc IVersioned * @inheritdoc IVersioned
* @custom:semver 0.0.2
*/ */
function version() external pure returns (string memory) { function version() external pure returns (string memory) {
return "0.0.1"; return "0.0.2";
} }
/** /**
* @inheritdoc IDisputeGameFactory * @inheritdoc IDisputeGameFactory
*/ */
function gameCount() external view returns (uint256 _gameCount) { function gameCount() external view returns (uint256 gameCount_) {
_gameCount = disputeGameList.length; gameCount_ = _disputeGameList.length;
} }
/** /**
* @inheritdoc IDisputeGameFactory * @inheritdoc IDisputeGameFactory
*/ */
function games( function games(
GameType gameType, GameType _gameType,
Claim rootClaim, Claim _rootClaim,
bytes calldata extraData bytes calldata _extraData
) external view returns (IDisputeGame _proxy) { ) external view returns (IDisputeGame proxy_, uint256 timestamp_) {
return disputeGames[getGameUUID(gameType, rootClaim, extraData)]; Hash uuid = getGameUUID(_gameType, _rootClaim, _extraData);
GameId slot = _disputeGames[uuid];
(address addr, uint256 timestamp) = _unpackSlot(slot);
proxy_ = IDisputeGame(addr);
timestamp_ = timestamp;
}
/**
* @inheritdoc IDisputeGameFactory
*/
function gameAtIndex(uint256 _index)
external
view
returns (IDisputeGame proxy_, uint256 timestamp_)
{
GameId slot = _disputeGameList[_index];
(address addr, uint256 timestamp) = _unpackSlot(slot);
proxy_ = IDisputeGame(addr);
timestamp_ = timestamp;
} }
/** /**
...@@ -107,13 +130,15 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, IVersion ...@@ -107,13 +130,15 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, IVersion
Hash uuid = getGameUUID(gameType, rootClaim, extraData); Hash uuid = getGameUUID(gameType, rootClaim, extraData);
// If a dispute game with the same UUID already exists, revert. // If a dispute game with the same UUID already exists, revert.
if (address(disputeGames[uuid]) != address(0)) { if (GameId.unwrap(_disputeGames[uuid]) != bytes32(0)) {
revert GameAlreadyExists(uuid); revert GameAlreadyExists(uuid);
} }
GameId slot = _packSlot(address(proxy), block.timestamp);
// Store the dispute game in the mapping & emit the `DisputeGameCreated` event. // Store the dispute game in the mapping & emit the `DisputeGameCreated` event.
disputeGames[uuid] = proxy; _disputeGames[uuid] = slot;
disputeGameList.push(proxy); _disputeGameList.push(slot);
emit DisputeGameCreated(address(proxy), gameType, rootClaim); emit DisputeGameCreated(address(proxy), gameType, rootClaim);
} }
...@@ -163,4 +188,24 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, IVersion ...@@ -163,4 +188,24 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, IVersion
gameImpls[gameType] = impl; gameImpls[gameType] = impl;
emit ImplementationSet(address(impl), gameType); emit ImplementationSet(address(impl), gameType);
} }
/**
* @dev Packs an address and a uint256 into a single bytes32 slot. This
* is only safe for up to uint96 values.
*/
function _packSlot(address _addr, uint256 _num) internal pure returns (GameId slot_) {
assembly {
slot_ := or(shl(0xa0, _num), _addr)
}
}
/**
* @dev Unpacks an address and a uint256 from a single bytes32 slot.
*/
function _unpackSlot(GameId _slot) internal pure returns (address addr_, uint256 num_) {
assembly {
addr_ := and(_slot, 0xffffffffffffffffffffffffffffffffffffffff)
num_ := shr(0xa0, _slot)
}
}
} }
...@@ -44,12 +44,26 @@ interface IDisputeGameFactory { ...@@ -44,12 +44,26 @@ interface IDisputeGameFactory {
* @param extraData Any extra data that should be provided to the created dispute game. * @param extraData Any extra data that should be provided to the created dispute game.
* @return _proxy The clone of the `DisputeGame` created with the given parameters. * @return _proxy The clone of the `DisputeGame` created with the given parameters.
* Returns `address(0)` if nonexistent. * Returns `address(0)` if nonexistent.
* @return _timestamp The timestamp of the creation of the dispute game.
*/ */
function games( function games(
GameType gameType, GameType gameType,
Claim rootClaim, Claim rootClaim,
bytes calldata extraData bytes calldata extraData
) external view returns (IDisputeGame _proxy); ) external view returns (IDisputeGame _proxy, uint256 _timestamp);
/**
* @notice `gameAtIndex` returns the dispute game contract address and its creation timestamp
* at the given index. Each created dispute game increments the underlying index.
* @param _index The index of the dispute game.
* @return _proxy The clone of the `DisputeGame` created with the given parameters.
* Returns `address(0)` if nonexistent.
* @return _timestamp The timestamp of the creation of the dispute game.
*/
function gameAtIndex(uint256 _index)
external
view
returns (IDisputeGame _proxy, uint256 _timestamp);
/** /**
* @notice `gameImpls` is a mapping that maps `GameType`s to their respective * @notice `gameImpls` is a mapping that maps `GameType`s to their respective
......
...@@ -33,6 +33,18 @@ type Timestamp is uint64; ...@@ -33,6 +33,18 @@ type Timestamp is uint64;
*/ */
type Duration is uint64; type Duration is uint64;
/**
* @notice A `GameId` represents a packed 12 byte timestamp and a 20 byte address.
* @dev The packed layout of this type is as follows:
* ┌────────────┬────────────────┐
* │ Bits │ Value │
* ├────────────┼────────────────┤
* │ [0, 96) │ Timestamp │
* │ [96, 256) │ Address │
* └────────────┴────────────────┘
*/
type GameId is bytes32;
/** /**
* @notice A `Clock` represents a packed `Duration` and `Timestamp` * @notice A `Clock` represents a packed `Duration` and `Timestamp`
* @dev The packed layout of this type is as follows: * @dev The packed layout of this type is as follows:
......
...@@ -9,8 +9,9 @@ import { DisputeGameFactory } from "../dispute/DisputeGameFactory.sol"; ...@@ -9,8 +9,9 @@ import { DisputeGameFactory } from "../dispute/DisputeGameFactory.sol";
import { IDisputeGame } from "../dispute/interfaces/IDisputeGame.sol"; import { IDisputeGame } from "../dispute/interfaces/IDisputeGame.sol";
import { Proxy } from "../universal/Proxy.sol"; import { Proxy } from "../universal/Proxy.sol";
contract DisputeGameFactory_Initializer is Test { contract DisputeGameFactory_Init is Test {
DisputeGameFactory factory; DisputeGameFactory factory;
FakeClone fakeClone;
event DisputeGameCreated( event DisputeGameCreated(
address indexed disputeProxy, address indexed disputeProxy,
...@@ -30,17 +31,12 @@ contract DisputeGameFactory_Initializer is Test { ...@@ -30,17 +31,12 @@ contract DisputeGameFactory_Initializer is Test {
}); });
factory = DisputeGameFactory(address(proxy)); factory = DisputeGameFactory(address(proxy));
vm.label(address(factory), "DisputeGameFactoryProxy"); vm.label(address(factory), "DisputeGameFactoryProxy");
}
}
contract DisputeGameFactory_Test is DisputeGameFactory_Initializer {
FakeClone fakeClone;
function setUp() public override {
super.setUp();
fakeClone = new FakeClone(); fakeClone = new FakeClone();
} }
}
contract DisputeGameFactory_Create_Test is DisputeGameFactory_Init {
/** /**
* @dev Tests that the `create` function succeeds when creating a new dispute game * @dev Tests that the `create` function succeeds when creating a new dispute game
* with a `GameType` that has an implementation set. * with a `GameType` that has an implementation set.
...@@ -62,10 +58,16 @@ contract DisputeGameFactory_Test is DisputeGameFactory_Initializer { ...@@ -62,10 +58,16 @@ contract DisputeGameFactory_Test is DisputeGameFactory_Initializer {
emit DisputeGameCreated(address(0), gt, rootClaim); emit DisputeGameCreated(address(0), gt, rootClaim);
IDisputeGame proxy = factory.create(gt, rootClaim, extraData); IDisputeGame proxy = factory.create(gt, rootClaim, extraData);
(IDisputeGame game, uint256 timestamp) = factory.games(gt, rootClaim, extraData);
// Ensure that the dispute game was assigned to the `disputeGames` mapping. // Ensure that the dispute game was assigned to the `disputeGames` mapping.
assertEq(address(factory.games(gt, rootClaim, extraData)), address(proxy)); assertEq(address(game), address(proxy));
assertEq(timestamp, block.timestamp);
assertEq(factory.gameCount(), 1); assertEq(factory.gameCount(), 1);
assertEq(address(factory.disputeGameList(0)), address(proxy));
(IDisputeGame game2, uint256 timestamp2) = factory.gameAtIndex(0);
assertEq(address(game2), address(proxy));
assertEq(timestamp2, block.timestamp);
} }
/** /**
...@@ -105,8 +107,10 @@ contract DisputeGameFactory_Test is DisputeGameFactory_Initializer { ...@@ -105,8 +107,10 @@ contract DisputeGameFactory_Test is DisputeGameFactory_Initializer {
emit DisputeGameCreated(address(0), gt, rootClaim); emit DisputeGameCreated(address(0), gt, rootClaim);
IDisputeGame proxy = factory.create(gt, rootClaim, extraData); IDisputeGame proxy = factory.create(gt, rootClaim, extraData);
(IDisputeGame game, uint256 timestamp) = factory.games(gt, rootClaim, extraData);
// Ensure that the dispute game was assigned to the `disputeGames` mapping. // Ensure that the dispute game was assigned to the `disputeGames` mapping.
assertEq(address(factory.games(gt, rootClaim, extraData)), address(proxy)); assertEq(address(game), address(proxy));
assertEq(timestamp, block.timestamp);
// Ensure that the `create` function reverts when called with parameters that would result in the same UUID. // Ensure that the `create` function reverts when called with parameters that would result in the same UUID.
vm.expectRevert( vm.expectRevert(
...@@ -117,7 +121,9 @@ contract DisputeGameFactory_Test is DisputeGameFactory_Initializer { ...@@ -117,7 +121,9 @@ contract DisputeGameFactory_Test is DisputeGameFactory_Initializer {
); );
factory.create(gt, rootClaim, extraData); factory.create(gt, rootClaim, extraData);
} }
}
contract DisputeGameFactory_SetImplementation_Test is DisputeGameFactory_Init {
/** /**
* @dev Tests that the `setImplementation` function properly sets the implementation for a given `GameType`. * @dev Tests that the `setImplementation` function properly sets the implementation for a given `GameType`.
*/ */
...@@ -144,7 +150,9 @@ contract DisputeGameFactory_Test is DisputeGameFactory_Initializer { ...@@ -144,7 +150,9 @@ contract DisputeGameFactory_Test is DisputeGameFactory_Initializer {
vm.expectRevert("Ownable: caller is not the owner"); vm.expectRevert("Ownable: caller is not the owner");
factory.setImplementation(GameTypes.FAULT, IDisputeGame(address(1))); factory.setImplementation(GameTypes.FAULT, IDisputeGame(address(1)));
} }
}
contract DisputeGameFactory_GetGameUUID_Test is DisputeGameFactory_Init {
/** /**
* @dev Tests that the `getGameUUID` function returns the correct hash when comparing * @dev Tests that the `getGameUUID` function returns the correct hash when comparing
* against the keccak256 hash of the abi-encoded parameters. * against the keccak256 hash of the abi-encoded parameters.
...@@ -162,14 +170,18 @@ contract DisputeGameFactory_Test is DisputeGameFactory_Initializer { ...@@ -162,14 +170,18 @@ contract DisputeGameFactory_Test is DisputeGameFactory_Initializer {
keccak256(abi.encode(gt, rootClaim, extraData)) keccak256(abi.encode(gt, rootClaim, extraData))
); );
} }
}
contract DisputeGameFactory_Owner_Test is DisputeGameFactory_Init {
/** /**
* @dev Tests that the `owner` function returns the correct address after deployment. * @dev Tests that the `owner` function returns the correct address after deployment.
*/ */
function test_owner_succeeds() public { function test_owner_succeeds() public {
assertEq(factory.owner(), address(this)); assertEq(factory.owner(), address(this));
} }
}
contract DisputeGameFactory_TransferOwnership_Test is DisputeGameFactory_Init {
/** /**
* @dev Tests that the `transferOwnership` function succeeds when called by the owner. * @dev Tests that the `transferOwnership` function succeeds when called by the owner.
*/ */
...@@ -188,6 +200,43 @@ contract DisputeGameFactory_Test is DisputeGameFactory_Initializer { ...@@ -188,6 +200,43 @@ contract DisputeGameFactory_Test is DisputeGameFactory_Initializer {
} }
} }
/**
* @title PackingTester
* @notice Exposes the internal packing functions so that they can be fuzzed
* in a roundtrip manner.
*/
contract PackingTester is DisputeGameFactory {
function packSlot(address _addr, uint256 _num) external pure returns (GameId) {
return _packSlot(_addr, _num);
}
function unpackSlot(GameId _slot) external pure returns (address, uint256) {
return _unpackSlot(_slot);
}
}
/**
* @title DisputeGameFactory_PackSlot_Test
* @notice Fuzzes the PackingTester contract
*/
contract DisputeGameFactory_PackSlot_Test is Test {
PackingTester tester;
function setUp() public {
tester = new PackingTester();
}
/**
* @dev Tests that the `packSlot` and `unpackSlot` functions roundtrip correctly.
*/
function testFuzz_packSlot_succeeds(address _addr, uint96 _num) public {
GameId slot = tester.packSlot(_addr, uint256(_num));
(address addr, uint256 num) = tester.unpackSlot(slot);
assertEq(addr, _addr);
assertEq(num, _num);
}
}
/** /**
* @dev A fake clone used for testing the `DisputeGameFactory` contract's `create` function. * @dev A fake clone used for testing the `DisputeGameFactory` contract's `create` function.
*/ */
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
pragma solidity ^0.8.15; pragma solidity ^0.8.15;
import { Test } from "forge-std/Test.sol"; import { Test } from "forge-std/Test.sol";
import { DisputeGameFactory_Initializer } from "./DisputeGameFactory.t.sol"; import { DisputeGameFactory_Init } from "./DisputeGameFactory.t.sol";
import { DisputeGameFactory } from "../dispute/DisputeGameFactory.sol"; import { DisputeGameFactory } from "../dispute/DisputeGameFactory.sol";
import { FaultDisputeGame } from "../dispute/FaultDisputeGame.sol"; import { FaultDisputeGame } from "../dispute/FaultDisputeGame.sol";
...@@ -11,7 +11,7 @@ import "../libraries/DisputeErrors.sol"; ...@@ -11,7 +11,7 @@ import "../libraries/DisputeErrors.sol";
import { LibClock } from "../dispute/lib/LibClock.sol"; import { LibClock } from "../dispute/lib/LibClock.sol";
import { LibPosition } from "../dispute/lib/LibPosition.sol"; import { LibPosition } from "../dispute/lib/LibPosition.sol";
contract FaultDisputeGame_Test is DisputeGameFactory_Initializer { contract FaultDisputeGame_Test is DisputeGameFactory_Init {
/** /**
* @dev The root claim of the game. * @dev The root claim of the game.
*/ */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment