diff --git a/packages/contracts/src/abis/utils/UnlockSwapPurchaser.json b/packages/contracts/src/abis/utils/UnlockSwapPurchaser.json index 521e0156ac7..cb1ea237d56 100644 --- a/packages/contracts/src/abis/utils/UnlockSwapPurchaser.json +++ b/packages/contracts/src/abis/utils/UnlockSwapPurchaser.json @@ -1,7 +1,7 @@ { "_format": "hh-sol-artifact-1", "contractName": "UnlockSwapPurchaser", - "sourceName": "contracts/utils/UnlockSwapPurchaser.sol", + "sourceName": "contracts/UnlockSwapPurchaser.flatten.sol", "abi": [ { "inputs": [ @@ -152,6 +152,11 @@ "name": "srcToken", "type": "address" }, + { + "internalType": "uint256", + "name": "keyPrice", + "type": "uint256" + }, { "internalType": "uint256", "name": "amountInMax", @@ -215,8 +220,8 @@ "type": "receive" } ], - "bytecode": "0x608060405234801562000010575f80fd5b50604051620010a9380380620010a9833981016040819052620000339162000103565b5f80546001600160a01b038086166001600160a01b031992831617835560018054918616919092161790555b8151811015620000c957600160025f848481518110620000835762000083620001f7565b6020908102919091018101516001600160a01b031682528101919091526040015f20805460ff191691151591909117905580620000c0816200020b565b9150506200005f565b5050505062000230565b80516001600160a01b0381168114620000ea575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f805f6060848603121562000116575f80fd5b6200012184620000d3565b9250602062000132818601620000d3565b60408601519093506001600160401b03808211156200014f575f80fd5b818701915087601f83011262000163575f80fd5b815181811115620001785762000178620000ef565b8060051b604051601f19603f83011681018181108582111715620001a057620001a0620000ef565b60405291825284820192508381018501918a831115620001be575f80fd5b938501935b82851015620001e757620001d785620000d3565b84529385019392850192620001c3565b8096505050505050509250925092565b634e487b7160e01b5f52603260045260245ffd5b5f600182016200022957634e487b7160e01b5f52601160045260245ffd5b5060010190565b610e6b806200023e5f395ff3fe608060405260043610610041575f3560e01c806302837f7b1461004c57806312261ee71461006d5780635e8f4502146100a2578063b30929cd146100c2575f80fd5b3661004857005b5f80fd5b348015610057575f80fd5b5061006b610066366004610b21565b6100e0565b005b348015610078575f80fd5b5060015461008c906001600160a01b031681565b6040516100999190610b43565b60405180910390f35b6100b56100b0366004610bf4565b6101e9565b6040516100999190610cdf565b3480156100cd575f80fd5b505f5461008c906001600160a01b031681565b5f6100ea8261084b565b90506001600160a01b03821615610173575f5460405163a9059cbb60e01b81526001600160a01b038481169263a9059cbb9261012e92909116908590600401610cf1565b6020604051808303815f875af115801561014a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061016e9190610d1e565b505050565b5f80546040516001600160a01b039091169083908381818185875af1925050503d805f81146101bd576040519150601f19603f3d011682016040523d82523d5f602084013e6101c2565b606091505b50909150508015155f0361016e57604051631d42c86760e21b815260040160405180910390fd5b5f8054604051635de9a13760e01b8152606092916001600160a01b031690635de9a1379061021b908b90600401610b43565b606060405180830381865afa158015610236573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061025a9190610d37565b50509050806102875787604051637421631960e11b815260040161027e9190610b43565b60405180910390fd5b6001600160a01b0385165f9081526002602052604090205460ff1615156001146102c6578460405163f2f52fc960e01b815260040161027e9190610b43565b5f886001600160a01b0316639d76ea586040518163ffffffff1660e01b8152600401602060405180830381865afa158015610303573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103279190610d69565b90505f6001600160a01b03821615610347576103428261084b565b61035b565b346103518361084b565b61035b9190610d98565b90505f6001600160a01b038a161561037b576103768a61084b565b61038f565b346103858b61084b565b61038f9190610d98565b90506001600160a01b038a161561042d576103ac8a33308c6108d3565b6103b78a898b6109d8565b60015460405163095ea7b360e01b81526001600160a01b038c81169263095ea7b3926103eb92909116908d90600401610cf1565b6020604051808303815f875af1158015610407573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061042b9190610d1e565b505b6001546001600160a01b03166387517c458b8a6104498d610add565b61045442603c610dab565b6040516001600160e01b031960e087901b1681526001600160a01b03948516600482015292841660248401529216604482015265ffffffffffff90911660648201526084015f604051808303815f87803b1580156104b0575f80fd5b505af11580156104c2573d5f803e3d5ffd5b505f9250506001600160a01b03808b1691508c16156104e1575f6104e3565b345b896040516104f19190610dbe565b5f6040518083038185875af1925050503d805f811461052b576040519150601f19603f3d011682016040523d82523d5f602084013e610530565b606091505b50909150508015155f0361056157888b858c8b604051637bd486e960e11b815260040161027e959493929190610dd9565b8b6001600160a01b03166310e569736040518163ffffffff1660e01b8152600401602060405180830381865afa15801561059d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105c19190610e1e565b6105cb9084610dab565b6001600160a01b038516156105e8576105e38561084b565b6105fc565b346105f28661084b565b6105fc9190610d98565b101561061b57604051631e9acf1760e31b815260040160405180910390fd5b6001600160a01b038416156106f957836001600160a01b031663095ea7b38d8e6001600160a01b03166310e569736040518163ffffffff1660e01b8152600401602060405180830381865afa158015610676573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061069a9190610e1e565b6040518363ffffffff1660e01b81526004016106b7929190610cf1565b6020604051808303815f875af11580156106d3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f79190610d1e565b505b5f806001600160a01b03808f1690871615610714575f610774565b8e6001600160a01b03166310e569736040518163ffffffff1660e01b8152600401602060405180830381865afa158015610750573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107749190610e1e565b8a6040516107829190610dbe565b5f6040518083038185875af1925050503d805f81146107bc576040519150601f19603f3d011682016040523d82523d5f602084013e6107c1565b606091505b5090925090508115155f036107e957604051637772507160e11b815260040160405180910390fd5b5f846107f48f61084b565b6107fe9190610d98565b108061081c57505f856108108861084b565b61081a9190610d98565b105b1561083a5760405163392032cb60e21b815260040160405180910390fd5b9d9c50505050505050505050505050565b5f6001600160a01b038216156108cb576040516370a0823160e01b81526001600160a01b038316906370a0823190610887903090600401610b43565b602060405180830381865afa1580156108a2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108c69190610e1e565b6108cd565b475b92915050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291515f928392908816916109369190610dbe565b5f604051808303815f865af19150503d805f811461096f576040519150601f19603f3d011682016040523d82523d5f602084013e610974565b606091505b509150915081801561099e57508051158061099e57508080602001905181019061099e9190610d1e565b6109d05760405162461bcd60e51b815260206004820152600360248201526229aa2360e91b604482015260640161027e565b505050505050565b5f80846001600160a01b031663095ea7b360e01b85856040516024016109ff929190610cf1565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051610a3d9190610dbe565b5f604051808303815f865af19150503d805f8114610a76576040519150601f19603f3d011682016040523d82523d5f602084013e610a7b565b606091505b5091509150818015610aa5575080511580610aa5575080806020019051810190610aa59190610d1e565b610ad65760405162461bcd60e51b8152602060048201526002602482015261534160f01b604482015260640161027e565b5050505050565b5f6001600160a01b03821115610b065760405163c4bd89a960e01b815260040160405180910390fd5b5090565b6001600160a01b0381168114610b1e575f80fd5b50565b5f60208284031215610b31575f80fd5b8135610b3c81610b0a565b9392505050565b6001600160a01b0391909116815260200190565b634e487b7160e01b5f52604160045260245ffd5b5f82601f830112610b7a575f80fd5b813567ffffffffffffffff80821115610b9557610b95610b57565b604051601f8301601f19908116603f01168101908282118183101715610bbd57610bbd610b57565b81604052838152866020858801011115610bd5575f80fd5b836020870160208301375f602085830101528094505050505092915050565b5f805f805f8060c08789031215610c09575f80fd5b8635610c1481610b0a565b95506020870135610c2481610b0a565b9450604087013593506060870135610c3b81610b0a565b9250608087013567ffffffffffffffff80821115610c57575f80fd5b610c638a838b01610b6b565b935060a0890135915080821115610c78575f80fd5b50610c8589828a01610b6b565b9150509295509295509295565b5f5b83811015610cac578181015183820152602001610c94565b50505f910152565b5f8151808452610ccb816020860160208601610c92565b601f01601f19169290920160200192915050565b602081525f610b3c6020830184610cb4565b6001600160a01b03929092168252602082015260400190565b80518015158114610d19575f80fd5b919050565b5f60208284031215610d2e575f80fd5b610b3c82610d0a565b5f805f60608486031215610d49575f80fd5b610d5284610d0a565b925060208401519150604084015190509250925092565b5f60208284031215610d79575f80fd5b8151610b3c81610b0a565b634e487b7160e01b5f52601160045260245ffd5b818103818111156108cd576108cd610d84565b808201808211156108cd576108cd610d84565b5f8251610dcf818460208701610c92565b9190910192915050565b6001600160a01b0386811682528581166020830152841660408201526060810183905260a0608082018190525f90610e1390830184610cb4565b979650505050505050565b5f60208284031215610e2e575f80fd5b505191905056fea26469706673582212205e967646e65cff1ceb719bc90aec4838b33ed8437ceb477be68091568f18898964736f6c63430008150033", - "deployedBytecode": "0x608060405260043610610041575f3560e01c806302837f7b1461004c57806312261ee71461006d5780635e8f4502146100a2578063b30929cd146100c2575f80fd5b3661004857005b5f80fd5b348015610057575f80fd5b5061006b610066366004610b21565b6100e0565b005b348015610078575f80fd5b5060015461008c906001600160a01b031681565b6040516100999190610b43565b60405180910390f35b6100b56100b0366004610bf4565b6101e9565b6040516100999190610cdf565b3480156100cd575f80fd5b505f5461008c906001600160a01b031681565b5f6100ea8261084b565b90506001600160a01b03821615610173575f5460405163a9059cbb60e01b81526001600160a01b038481169263a9059cbb9261012e92909116908590600401610cf1565b6020604051808303815f875af115801561014a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061016e9190610d1e565b505050565b5f80546040516001600160a01b039091169083908381818185875af1925050503d805f81146101bd576040519150601f19603f3d011682016040523d82523d5f602084013e6101c2565b606091505b50909150508015155f0361016e57604051631d42c86760e21b815260040160405180910390fd5b5f8054604051635de9a13760e01b8152606092916001600160a01b031690635de9a1379061021b908b90600401610b43565b606060405180830381865afa158015610236573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061025a9190610d37565b50509050806102875787604051637421631960e11b815260040161027e9190610b43565b60405180910390fd5b6001600160a01b0385165f9081526002602052604090205460ff1615156001146102c6578460405163f2f52fc960e01b815260040161027e9190610b43565b5f886001600160a01b0316639d76ea586040518163ffffffff1660e01b8152600401602060405180830381865afa158015610303573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103279190610d69565b90505f6001600160a01b03821615610347576103428261084b565b61035b565b346103518361084b565b61035b9190610d98565b90505f6001600160a01b038a161561037b576103768a61084b565b61038f565b346103858b61084b565b61038f9190610d98565b90506001600160a01b038a161561042d576103ac8a33308c6108d3565b6103b78a898b6109d8565b60015460405163095ea7b360e01b81526001600160a01b038c81169263095ea7b3926103eb92909116908d90600401610cf1565b6020604051808303815f875af1158015610407573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061042b9190610d1e565b505b6001546001600160a01b03166387517c458b8a6104498d610add565b61045442603c610dab565b6040516001600160e01b031960e087901b1681526001600160a01b03948516600482015292841660248401529216604482015265ffffffffffff90911660648201526084015f604051808303815f87803b1580156104b0575f80fd5b505af11580156104c2573d5f803e3d5ffd5b505f9250506001600160a01b03808b1691508c16156104e1575f6104e3565b345b896040516104f19190610dbe565b5f6040518083038185875af1925050503d805f811461052b576040519150601f19603f3d011682016040523d82523d5f602084013e610530565b606091505b50909150508015155f0361056157888b858c8b604051637bd486e960e11b815260040161027e959493929190610dd9565b8b6001600160a01b03166310e569736040518163ffffffff1660e01b8152600401602060405180830381865afa15801561059d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105c19190610e1e565b6105cb9084610dab565b6001600160a01b038516156105e8576105e38561084b565b6105fc565b346105f28661084b565b6105fc9190610d98565b101561061b57604051631e9acf1760e31b815260040160405180910390fd5b6001600160a01b038416156106f957836001600160a01b031663095ea7b38d8e6001600160a01b03166310e569736040518163ffffffff1660e01b8152600401602060405180830381865afa158015610676573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061069a9190610e1e565b6040518363ffffffff1660e01b81526004016106b7929190610cf1565b6020604051808303815f875af11580156106d3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f79190610d1e565b505b5f806001600160a01b03808f1690871615610714575f610774565b8e6001600160a01b03166310e569736040518163ffffffff1660e01b8152600401602060405180830381865afa158015610750573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107749190610e1e565b8a6040516107829190610dbe565b5f6040518083038185875af1925050503d805f81146107bc576040519150601f19603f3d011682016040523d82523d5f602084013e6107c1565b606091505b5090925090508115155f036107e957604051637772507160e11b815260040160405180910390fd5b5f846107f48f61084b565b6107fe9190610d98565b108061081c57505f856108108861084b565b61081a9190610d98565b105b1561083a5760405163392032cb60e21b815260040160405180910390fd5b9d9c50505050505050505050505050565b5f6001600160a01b038216156108cb576040516370a0823160e01b81526001600160a01b038316906370a0823190610887903090600401610b43565b602060405180830381865afa1580156108a2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108c69190610e1e565b6108cd565b475b92915050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291515f928392908816916109369190610dbe565b5f604051808303815f865af19150503d805f811461096f576040519150601f19603f3d011682016040523d82523d5f602084013e610974565b606091505b509150915081801561099e57508051158061099e57508080602001905181019061099e9190610d1e565b6109d05760405162461bcd60e51b815260206004820152600360248201526229aa2360e91b604482015260640161027e565b505050505050565b5f80846001600160a01b031663095ea7b360e01b85856040516024016109ff929190610cf1565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051610a3d9190610dbe565b5f604051808303815f865af19150503d805f8114610a76576040519150601f19603f3d011682016040523d82523d5f602084013e610a7b565b606091505b5091509150818015610aa5575080511580610aa5575080806020019051810190610aa59190610d1e565b610ad65760405162461bcd60e51b8152602060048201526002602482015261534160f01b604482015260640161027e565b5050505050565b5f6001600160a01b03821115610b065760405163c4bd89a960e01b815260040160405180910390fd5b5090565b6001600160a01b0381168114610b1e575f80fd5b50565b5f60208284031215610b31575f80fd5b8135610b3c81610b0a565b9392505050565b6001600160a01b0391909116815260200190565b634e487b7160e01b5f52604160045260245ffd5b5f82601f830112610b7a575f80fd5b813567ffffffffffffffff80821115610b9557610b95610b57565b604051601f8301601f19908116603f01168101908282118183101715610bbd57610bbd610b57565b81604052838152866020858801011115610bd5575f80fd5b836020870160208301375f602085830101528094505050505092915050565b5f805f805f8060c08789031215610c09575f80fd5b8635610c1481610b0a565b95506020870135610c2481610b0a565b9450604087013593506060870135610c3b81610b0a565b9250608087013567ffffffffffffffff80821115610c57575f80fd5b610c638a838b01610b6b565b935060a0890135915080821115610c78575f80fd5b50610c8589828a01610b6b565b9150509295509295509295565b5f5b83811015610cac578181015183820152602001610c94565b50505f910152565b5f8151808452610ccb816020860160208601610c92565b601f01601f19169290920160200192915050565b602081525f610b3c6020830184610cb4565b6001600160a01b03929092168252602082015260400190565b80518015158114610d19575f80fd5b919050565b5f60208284031215610d2e575f80fd5b610b3c82610d0a565b5f805f60608486031215610d49575f80fd5b610d5284610d0a565b925060208401519150604084015190509250925092565b5f60208284031215610d79575f80fd5b8151610b3c81610b0a565b634e487b7160e01b5f52601160045260245ffd5b818103818111156108cd576108cd610d84565b808201808211156108cd576108cd610d84565b5f8251610dcf818460208701610c92565b9190910192915050565b6001600160a01b0386811682528581166020830152841660408201526060810183905260a0608082018190525f90610e1390830184610cb4565b979650505050505050565b5f60208284031215610e2e575f80fd5b505191905056fea26469706673582212205e967646e65cff1ceb719bc90aec4838b33ed8437ceb477be68091568f18898964736f6c63430008150033", + "bytecode": "0x608060405234801562000010575f80fd5b5060405162000fa238038062000fa2833981016040819052620000339162000103565b5f80546001600160a01b038086166001600160a01b031992831617835560018054918616919092161790555b8151811015620000c957600160025f848481518110620000835762000083620001f7565b6020908102919091018101516001600160a01b031682528101919091526040015f20805460ff191691151591909117905580620000c0816200020b565b9150506200005f565b5050505062000230565b80516001600160a01b0381168114620000ea575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f805f6060848603121562000116575f80fd5b6200012184620000d3565b9250602062000132818601620000d3565b60408601519093506001600160401b03808211156200014f575f80fd5b818701915087601f83011262000163575f80fd5b815181811115620001785762000178620000ef565b8060051b604051601f19603f83011681018181108582111715620001a057620001a0620000ef565b60405291825284820192508381018501918a831115620001be575f80fd5b938501935b82851015620001e757620001d785620000d3565b84529385019392850192620001c3565b8096505050505050509250925092565b634e487b7160e01b5f52603260045260245ffd5b5f600182016200022957634e487b7160e01b5f52601160045260245ffd5b5060010190565b610d64806200023e5f395ff3fe608060405260043610610041575f3560e01c806302837f7b1461004c57806312261ee71461006d57806315813ad2146100a2578063b30929cd146100c2575f80fd5b3661004857005b5f80fd5b348015610057575f80fd5b5061006b610066366004610a15565b6100e0565b005b348015610078575f80fd5b5060015461008c906001600160a01b031681565b6040516100999190610a37565b60405180910390f35b6100b56100b0366004610ae8565b6101e9565b6040516100999190610bdd565b3480156100cd575f80fd5b505f5461008c906001600160a01b031681565b5f6100ea826106a5565b90506001600160a01b03821615610173575f5460405163a9059cbb60e01b81526001600160a01b038481169263a9059cbb9261012e92909116908590600401610bef565b6020604051808303815f875af115801561014a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061016e9190610c17565b505050565b5f80546040516001600160a01b039091169083908381818185875af1925050503d805f81146101bd576040519150601f19603f3d011682016040523d82523d5f602084013e6101c2565b606091505b50909150508015155f0361016e57604051631d42c86760e21b815260040160405180910390fd5b60606101f48861072d565b506001600160a01b0384165f9081526002602052604090205460ff16151560011461023d578360405163f2f52fc960e01b81526004016102349190610a37565b60405180910390fd5b5f886001600160a01b0316639d76ea586040518163ffffffff1660e01b8152600401602060405180830381865afa15801561027a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061029e9190610c30565b90505f6001600160a01b038216156102be576102b9826106a5565b6102d2565b346102c8836106a5565b6102d29190610c5f565b90505f6001600160a01b038a16156102f2576102ed8a6106a5565b610306565b346102fc8b6106a5565b6103069190610c5f565b90506001600160a01b038a16156103a4576103238a33308b6107c7565b61032e8a888a6108cc565b60015460405163095ea7b360e01b81526001600160a01b038c81169263095ea7b39261036292909116908c90600401610bef565b6020604051808303815f875af115801561037e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103a29190610c17565b505b6001546001600160a01b03166387517c458b896103c08c6109d1565b6103cb42603c610c72565b6040516001600160e01b031960e087901b1681526001600160a01b03948516600482015292841660248401529216604482015265ffffffffffff90911660648201526084015f604051808303815f87803b158015610427575f80fd5b505af1158015610439573d5f803e3d5ffd5b505f9250506001600160a01b03808a1691508c1615610458575f61045a565b345b886040516104689190610c85565b5f6040518083038185875af1925050503d805f81146104a2576040519150601f19603f3d011682016040523d82523d5f602084013e6104a7565b606091505b50909150508015155f036104d857878b858b8a604051637bd486e960e11b8152600401610234959493929190610ca0565b6104e28a84610c72565b6001600160a01b038516156104ff576104fa856106a5565b610513565b34610509866106a5565b6105139190610c5f565b101561053257604051631e9acf1760e31b815260040160405180910390fd5b6001600160a01b038416156105b15760405163095ea7b360e01b81526001600160a01b0385169063095ea7b39061056f908f908e90600401610bef565b6020604051808303815f875af115801561058b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105af9190610c17565b505b5f806001600160a01b03808f16908716156105cc575f6105ce565b8c5b896040516105dc9190610c85565b5f6040518083038185875af1925050503d805f8114610616576040519150601f19603f3d011682016040523d82523d5f602084013e61061b565b606091505b5090925090508115155f0361064357604051637772507160e11b815260040160405180910390fd5b5f8461064e8f6106a5565b6106589190610c5f565b108061067657505f8561066a886106a5565b6106749190610c5f565b105b156106945760405163392032cb60e21b815260040160405180910390fd5b9d9c50505050505050505050505050565b5f6001600160a01b03821615610725576040516370a0823160e01b81526001600160a01b038316906370a08231906106e1903090600401610a37565b602060405180830381865afa1580156106fc573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107209190610ce5565b610727565b475b92915050565b5f8054604051635de9a13760e01b81526001600160a01b0390911690635de9a1379061075d908590600401610a37565b606060405180830381865afa158015610778573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061079c9190610cfc565b509091508190506107c25781604051637421631960e11b81526004016102349190610a37565b919050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291515f9283929088169161082a9190610c85565b5f604051808303815f865af19150503d805f8114610863576040519150601f19603f3d011682016040523d82523d5f602084013e610868565b606091505b50915091508180156108925750805115806108925750808060200190518101906108929190610c17565b6108c45760405162461bcd60e51b815260206004820152600360248201526229aa2360e91b6044820152606401610234565b505050505050565b5f80846001600160a01b031663095ea7b360e01b85856040516024016108f3929190610bef565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516109319190610c85565b5f604051808303815f865af19150503d805f811461096a576040519150601f19603f3d011682016040523d82523d5f602084013e61096f565b606091505b50915091508180156109995750805115806109995750808060200190518101906109999190610c17565b6109ca5760405162461bcd60e51b8152602060048201526002602482015261534160f01b6044820152606401610234565b5050505050565b5f6001600160a01b038211156109fa5760405163c4bd89a960e01b815260040160405180910390fd5b5090565b6001600160a01b0381168114610a12575f80fd5b50565b5f60208284031215610a25575f80fd5b8135610a30816109fe565b9392505050565b6001600160a01b0391909116815260200190565b634e487b7160e01b5f52604160045260245ffd5b5f82601f830112610a6e575f80fd5b813567ffffffffffffffff80821115610a8957610a89610a4b565b604051601f8301601f19908116603f01168101908282118183101715610ab157610ab1610a4b565b81604052838152866020858801011115610ac9575f80fd5b836020870160208301375f602085830101528094505050505092915050565b5f805f805f805f60e0888a031215610afe575f80fd5b8735610b09816109fe565b96506020880135610b19816109fe565b955060408801359450606088013593506080880135610b37816109fe565b925060a088013567ffffffffffffffff80821115610b53575f80fd5b610b5f8b838c01610a5f565b935060c08a0135915080821115610b74575f80fd5b50610b818a828b01610a5f565b91505092959891949750929550565b5f5b83811015610baa578181015183820152602001610b92565b50505f910152565b5f8151808452610bc9816020860160208601610b90565b601f01601f19169290920160200192915050565b602081525f610a306020830184610bb2565b6001600160a01b03929092168252602082015260400190565b805180151581146107c2575f80fd5b5f60208284031215610c27575f80fd5b610a3082610c08565b5f60208284031215610c40575f80fd5b8151610a30816109fe565b634e487b7160e01b5f52601160045260245ffd5b8181038181111561072757610727610c4b565b8082018082111561072757610727610c4b565b5f8251610c96818460208701610b90565b9190910192915050565b6001600160a01b0386811682528581166020830152841660408201526060810183905260a0608082018190525f90610cda90830184610bb2565b979650505050505050565b5f60208284031215610cf5575f80fd5b5051919050565b5f805f60608486031215610d0e575f80fd5b610d1784610c08565b92506020840151915060408401519050925092509256fea2646970667358221220ea3bd5c7b5509cb7c168f012e8cf37063f84b2c03f1510b84a3df402559e861864736f6c63430008150033", + "deployedBytecode": "0x608060405260043610610041575f3560e01c806302837f7b1461004c57806312261ee71461006d57806315813ad2146100a2578063b30929cd146100c2575f80fd5b3661004857005b5f80fd5b348015610057575f80fd5b5061006b610066366004610a15565b6100e0565b005b348015610078575f80fd5b5060015461008c906001600160a01b031681565b6040516100999190610a37565b60405180910390f35b6100b56100b0366004610ae8565b6101e9565b6040516100999190610bdd565b3480156100cd575f80fd5b505f5461008c906001600160a01b031681565b5f6100ea826106a5565b90506001600160a01b03821615610173575f5460405163a9059cbb60e01b81526001600160a01b038481169263a9059cbb9261012e92909116908590600401610bef565b6020604051808303815f875af115801561014a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061016e9190610c17565b505050565b5f80546040516001600160a01b039091169083908381818185875af1925050503d805f81146101bd576040519150601f19603f3d011682016040523d82523d5f602084013e6101c2565b606091505b50909150508015155f0361016e57604051631d42c86760e21b815260040160405180910390fd5b60606101f48861072d565b506001600160a01b0384165f9081526002602052604090205460ff16151560011461023d578360405163f2f52fc960e01b81526004016102349190610a37565b60405180910390fd5b5f886001600160a01b0316639d76ea586040518163ffffffff1660e01b8152600401602060405180830381865afa15801561027a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061029e9190610c30565b90505f6001600160a01b038216156102be576102b9826106a5565b6102d2565b346102c8836106a5565b6102d29190610c5f565b90505f6001600160a01b038a16156102f2576102ed8a6106a5565b610306565b346102fc8b6106a5565b6103069190610c5f565b90506001600160a01b038a16156103a4576103238a33308b6107c7565b61032e8a888a6108cc565b60015460405163095ea7b360e01b81526001600160a01b038c81169263095ea7b39261036292909116908c90600401610bef565b6020604051808303815f875af115801561037e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103a29190610c17565b505b6001546001600160a01b03166387517c458b896103c08c6109d1565b6103cb42603c610c72565b6040516001600160e01b031960e087901b1681526001600160a01b03948516600482015292841660248401529216604482015265ffffffffffff90911660648201526084015f604051808303815f87803b158015610427575f80fd5b505af1158015610439573d5f803e3d5ffd5b505f9250506001600160a01b03808a1691508c1615610458575f61045a565b345b886040516104689190610c85565b5f6040518083038185875af1925050503d805f81146104a2576040519150601f19603f3d011682016040523d82523d5f602084013e6104a7565b606091505b50909150508015155f036104d857878b858b8a604051637bd486e960e11b8152600401610234959493929190610ca0565b6104e28a84610c72565b6001600160a01b038516156104ff576104fa856106a5565b610513565b34610509866106a5565b6105139190610c5f565b101561053257604051631e9acf1760e31b815260040160405180910390fd5b6001600160a01b038416156105b15760405163095ea7b360e01b81526001600160a01b0385169063095ea7b39061056f908f908e90600401610bef565b6020604051808303815f875af115801561058b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105af9190610c17565b505b5f806001600160a01b03808f16908716156105cc575f6105ce565b8c5b896040516105dc9190610c85565b5f6040518083038185875af1925050503d805f8114610616576040519150601f19603f3d011682016040523d82523d5f602084013e61061b565b606091505b5090925090508115155f0361064357604051637772507160e11b815260040160405180910390fd5b5f8461064e8f6106a5565b6106589190610c5f565b108061067657505f8561066a886106a5565b6106749190610c5f565b105b156106945760405163392032cb60e21b815260040160405180910390fd5b9d9c50505050505050505050505050565b5f6001600160a01b03821615610725576040516370a0823160e01b81526001600160a01b038316906370a08231906106e1903090600401610a37565b602060405180830381865afa1580156106fc573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107209190610ce5565b610727565b475b92915050565b5f8054604051635de9a13760e01b81526001600160a01b0390911690635de9a1379061075d908590600401610a37565b606060405180830381865afa158015610778573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061079c9190610cfc565b509091508190506107c25781604051637421631960e11b81526004016102349190610a37565b919050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291515f9283929088169161082a9190610c85565b5f604051808303815f865af19150503d805f8114610863576040519150601f19603f3d011682016040523d82523d5f602084013e610868565b606091505b50915091508180156108925750805115806108925750808060200190518101906108929190610c17565b6108c45760405162461bcd60e51b815260206004820152600360248201526229aa2360e91b6044820152606401610234565b505050505050565b5f80846001600160a01b031663095ea7b360e01b85856040516024016108f3929190610bef565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516109319190610c85565b5f604051808303815f865af19150503d805f811461096a576040519150601f19603f3d011682016040523d82523d5f602084013e61096f565b606091505b50915091508180156109995750805115806109995750808060200190518101906109999190610c17565b6109ca5760405162461bcd60e51b8152602060048201526002602482015261534160f01b6044820152606401610234565b5050505050565b5f6001600160a01b038211156109fa5760405163c4bd89a960e01b815260040160405180910390fd5b5090565b6001600160a01b0381168114610a12575f80fd5b50565b5f60208284031215610a25575f80fd5b8135610a30816109fe565b9392505050565b6001600160a01b0391909116815260200190565b634e487b7160e01b5f52604160045260245ffd5b5f82601f830112610a6e575f80fd5b813567ffffffffffffffff80821115610a8957610a89610a4b565b604051601f8301601f19908116603f01168101908282118183101715610ab157610ab1610a4b565b81604052838152866020858801011115610ac9575f80fd5b836020870160208301375f602085830101528094505050505092915050565b5f805f805f805f60e0888a031215610afe575f80fd5b8735610b09816109fe565b96506020880135610b19816109fe565b955060408801359450606088013593506080880135610b37816109fe565b925060a088013567ffffffffffffffff80821115610b53575f80fd5b610b5f8b838c01610a5f565b935060c08a0135915080821115610b74575f80fd5b50610b818a828b01610a5f565b91505092959891949750929550565b5f5b83811015610baa578181015183820152602001610b92565b50505f910152565b5f8151808452610bc9816020860160208601610b90565b601f01601f19169290920160200192915050565b602081525f610a306020830184610bb2565b6001600160a01b03929092168252602082015260400190565b805180151581146107c2575f80fd5b5f60208284031215610c27575f80fd5b610a3082610c08565b5f60208284031215610c40575f80fd5b8151610a30816109fe565b634e487b7160e01b5f52601160045260245ffd5b8181038181111561072757610727610c4b565b8082018082111561072757610727610c4b565b5f8251610c96818460208701610b90565b9190910192915050565b6001600160a01b0386811682528581166020830152841660408201526060810183905260a0608082018190525f90610cda90830184610bb2565b979650505050505050565b5f60208284031215610cf5575f80fd5b5051919050565b5f805f60608486031215610d0e575f80fd5b610d1784610c08565b92506020840151915060408401519050925092509256fea2646970667358221220ea3bd5c7b5509cb7c168f012e8cf37063f84b2c03f1510b84a3df402559e861864736f6c63430008150033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/packages/contracts/src/contracts/utils/UnlockSwapPurchaser.sol b/packages/contracts/src/contracts/utils/UnlockSwapPurchaser.sol index b521bf6d5e3..3aadc8c9055 100644 --- a/packages/contracts/src/contracts/utils/UnlockSwapPurchaser.sol +++ b/packages/contracts/src/contracts/utils/UnlockSwapPurchaser.sol @@ -1,4 +1,4 @@ -// Sources flattened with hardhat v2.18.3 https://hardhat.org +// Sources flattened with hardhat v2.20.1 https://hardhat.org // SPDX-License-Identifier: GPL-2.0-or-later AND MIT @@ -749,17 +749,24 @@ interface IPublicLock { * - `from`, `to` cannot be zero. * - `tokenId` must be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move this - * NFT by either {approve} or {setApprovalForAll}. + * NFT by either `approve` or `setApprovalForAll`. */ function safeTransferFrom(address from, address to, uint256 tokenId) external; + function safeTransferFrom( + address from, + address to, + uint256 tokenId, + bytes calldata data + ) external; + /** * an ERC721-like function to transfer a token from one account to another. * @param from the owner of token to transfer * @param to the address that will receive the token * @param tokenId the id of the token * @dev Requirements: if the caller is not `from`, it must be approved to move this token by - * either {approve} or {setApprovalForAll}. + * either `approve` or `setApprovalForAll`. * The key manager will be reset to address zero after the transfer */ function transferFrom(address from, address to, uint256 tokenId) external; @@ -816,13 +823,6 @@ interface IPublicLock { address _operator ) external view returns (bool); - function safeTransferFrom( - address from, - address to, - uint256 tokenId, - bytes calldata data - ) external; - /** * Returns the total number of keys, including non-valid ones * @return _totalKeysCreated the total number of keys, valid or not @@ -1332,6 +1332,17 @@ contract UnlockSwapPurchaser { : IMintableERC20(token).balanceOf(address(this)); } + /** + * Check if lock exists + * @param lock address of the lock + */ + function lockExists(address lock) internal view returns (bool lockExists) { + (lockExists, , ) = IUnlock(unlockAddress).locks(lock); + if (!lockExists) { + revert LockDoesntExist(lock); + } + } + /** * Swap tokens and call a function a lock contract. * @@ -1340,6 +1351,7 @@ contract UnlockSwapPurchaser { * * @param lock the address of the lock * @param srcToken the address of the token sent by the user (ERC20 or address(0) for native) + * @param keyPrice the expected price of the token (calculated from the lock) * @param amountInMax the maximum amount the user want to spend in the swap * @param uniswapRouter the address of the uniswap router * @param swapCalldata the Uniswap quote calldata returned by the SDK, to be sent to the router contract @@ -1353,18 +1365,15 @@ contract UnlockSwapPurchaser { function swapAndCall( address lock, address srcToken, + uint keyPrice, uint amountInMax, address uniswapRouter, bytes memory swapCalldata, bytes memory callData ) public payable returns (bytes memory) { - // check if lock exists - (bool lockExists, , ) = IUnlock(unlockAddress).locks(lock); - if (!lockExists) { - revert LockDoesntExist(lock); - } + // make sure the lock is registered in Unlock + lockExists(lock); - // make sure if (uniswapRouters[uniswapRouter] != true) { revert UnautorizedRouter(uniswapRouter); } @@ -1428,19 +1437,19 @@ contract UnlockSwapPurchaser { destToken == address(0) ? getBalance(destToken) - msg.value : getBalance(destToken) - ) < balanceTokenDestBefore + IPublicLock(lock).keyPrice() + ) < balanceTokenDestBefore + keyPrice ) { revert InsufficientBalance(); } // approve ERC20 to call the lock if (destToken != address(0)) { - IMintableERC20(destToken).approve(lock, IPublicLock(lock).keyPrice()); + IMintableERC20(destToken).approve(lock, keyPrice); } // call the lock (bool lockCallSuccess, bytes memory returnData) = lock.call{ - value: destToken == address(0) ? IPublicLock(lock).keyPrice() : 0 + value: destToken == address(0) ? keyPrice : 0 }(callData); if (lockCallSuccess == false) { diff --git a/packages/contracts/src/index.ts b/packages/contracts/src/index.ts index 078391ede36..a3029bae3c6 100644 --- a/packages/contracts/src/index.ts +++ b/packages/contracts/src/index.ts @@ -77,9 +77,4 @@ export { UnlockDiscountTokenV2 } export { UnlockDiscountTokenV3 } export { GovernorUnlockProtocol } export { GovernorUnlockProtocolTimelock } -export { - LockSerializer, - UnlockSwapPurchaser, - UnlockSwapBurner, - UniswapOracleV3, -} +export { LockSerializer,UnlockSwapPurchaser,UnlockSwapBurner,UniswapOracleV3 } diff --git a/packages/hardhat-helpers/src/deploy.js b/packages/hardhat-helpers/src/deploy.js index b16178b63b0..a94eb144d54 100644 --- a/packages/hardhat-helpers/src/deploy.js +++ b/packages/hardhat-helpers/src/deploy.js @@ -24,17 +24,15 @@ export const deployContract = async ( console.log(` > contract deployed at : ${address} (tx: ${hash})`) if (!(await isLocalhost())) { - const args = { + const verifyArgs = { address, deployArgs, } - - // pass fully qualified path for verification if (typeof contractNameOrFullyQualifiedNameOrEthersFactory === 'string') { - args.contract = contractNameOrFullyQualifiedNameOrEthersFactory + verifyArgs.contract = contractNameOrFullyQualifiedNameOrEthersFactory } - await verify(args) + await verify(verifyArgs) } return { diff --git a/packages/networks/src/networks/arbitrum.ts b/packages/networks/src/networks/arbitrum.ts index 895c0d2c952..38599336cc0 100644 --- a/packages/networks/src/networks/arbitrum.ts +++ b/packages/networks/src/networks/arbitrum.ts @@ -80,7 +80,7 @@ export const arbitrum: NetworkConfig = { networkName: 'arbitrum-one', studioName: 'unlock-protocol-arbitrum', }, - swapPurchaser: '0x0C33884Ab3eE799E7628FA3fCF20B81997745a72', + swapPurchaser: '0xE1a7Ec44fB4c5c88ebB3744A9Ba2A3cCA879A47d', tokens: [ { address: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1', diff --git a/packages/networks/src/networks/avalanche.ts b/packages/networks/src/networks/avalanche.ts index 0cb9097efbb..5e3fb0c15e7 100644 --- a/packages/networks/src/networks/avalanche.ts +++ b/packages/networks/src/networks/avalanche.ts @@ -65,7 +65,7 @@ export const avalanche: NetworkConfig = { 'https://api.studio.thegraph.com/query/65299/unlock-protocol-avalanche/version/latest', studioName: 'unlock-protocol-avalanche', }, - swapPurchaser: '0x5c67AD0CAfe61aF3706347aBc695D7ACcb38EFb3', + swapPurchaser: '0xc9F29DdBD4D828cFb2EB491E9d48013a9c0E3C89', tokens: [ { address: '0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB', diff --git a/packages/networks/src/networks/base.ts b/packages/networks/src/networks/base.ts index 34572fe78df..3a3f57e776b 100644 --- a/packages/networks/src/networks/base.ts +++ b/packages/networks/src/networks/base.ts @@ -79,7 +79,7 @@ export const base: NetworkConfig = { networkName: 'base', studioName: 'unlock-protocol-base', }, - swapPurchaser: '0x70B3c9Dd9788570FAAb24B92c3a57d99f8186Cc7', + swapPurchaser: '0x36b34e10295cCE69B652eEB5a8046041074515Da', tokens: [ { address: '0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb', diff --git a/packages/networks/src/networks/bsc.ts b/packages/networks/src/networks/bsc.ts index 7a874c96e5d..c54dceb9d56 100644 --- a/packages/networks/src/networks/bsc.ts +++ b/packages/networks/src/networks/bsc.ts @@ -91,7 +91,7 @@ export const bsc: NetworkConfig = { studioName: 'unlock-protocol-bsc', }, - swapPurchaser: '0xc9F29DdBD4D828cFb2EB491E9d48013a9c0E3C89', + swapPurchaser: '0xe49f5FD63cD7ec130B07dad30f068CC08F201e1e', tokens: [ { diff --git a/packages/networks/src/networks/celo.ts b/packages/networks/src/networks/celo.ts index 407f04f7b52..5e678fe8713 100644 --- a/packages/networks/src/networks/celo.ts +++ b/packages/networks/src/networks/celo.ts @@ -59,7 +59,7 @@ export const celo: NetworkConfig = { 'https://api.studio.thegraph.com/query/65299/unlock-protocol-celo/version/latest', studioName: 'unlock-protocol-celo', }, - swapPurchaser: '0x42F5c7839Bf00FAea6ca09517E96E82e7364384D', + swapPurchaser: '0x440d9D4E66d39bb28FB58729Cb4D3ead2A595591', tokens: [ { address: '0xef4229c8c3250C675F21BCefa42f58EfbfF6002a', diff --git a/packages/networks/src/networks/optimism.ts b/packages/networks/src/networks/optimism.ts index 35195f1e181..6fb04d684ea 100644 --- a/packages/networks/src/networks/optimism.ts +++ b/packages/networks/src/networks/optimism.ts @@ -85,7 +85,7 @@ export const optimism: NetworkConfig = { 'https://api.studio.thegraph.com/query/65299/unlock-protocol-optimism/version/latest', studioName: 'unlock-protocol-optimism', }, - swapPurchaser: '0x72381052e4F7765A00a403891420BF75876c75bB', + swapPurchaser: '0x1bd356194d97297F77e081fFFAB97b57297E93e4', tokens: [ { address: '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', diff --git a/packages/networks/src/networks/sepolia.ts b/packages/networks/src/networks/sepolia.ts index 7b09dfbcd53..2e8abbfbd6a 100644 --- a/packages/networks/src/networks/sepolia.ts +++ b/packages/networks/src/networks/sepolia.ts @@ -84,7 +84,8 @@ export const sepolia: NetworkConfig = { networkName: 'sepolia', studioName: 'unlock-protocol-sepolia', }, - swapPurchaser: '0x580A4a5a9612371e3832c4559026B9Ee3b23Cc11', + + swapPurchaser: '0x692EFe2b44a531013A558E595C5dCf37DB2e4B94', tokens: [ { address: '0x7b79995e5f793A07Bc00c21412e50Ecae098E7f9', diff --git a/smart-contracts/contracts/utils/UnlockSwapPurchaser.sol b/smart-contracts/contracts/utils/UnlockSwapPurchaser.sol index edb8558c2d3..c338ac08cd0 100644 --- a/smart-contracts/contracts/utils/UnlockSwapPurchaser.sol +++ b/smart-contracts/contracts/utils/UnlockSwapPurchaser.sol @@ -77,6 +77,17 @@ contract UnlockSwapPurchaser { : IMintableERC20(token).balanceOf(address(this)); } + /** + * Check if lock exists + * @param lock address of the lock + */ + function lockExists(address lock) internal view returns (bool lockExists) { + (lockExists, , ) = IUnlock(unlockAddress).locks(lock); + if (!lockExists) { + revert LockDoesntExist(lock); + } + } + /** * Swap tokens and call a function a lock contract. * @@ -85,6 +96,7 @@ contract UnlockSwapPurchaser { * * @param lock the address of the lock * @param srcToken the address of the token sent by the user (ERC20 or address(0) for native) + * @param keyPrice the expected price of the token (calculated from the lock) * @param amountInMax the maximum amount the user want to spend in the swap * @param uniswapRouter the address of the uniswap router * @param swapCalldata the Uniswap quote calldata returned by the SDK, to be sent to the router contract @@ -98,18 +110,15 @@ contract UnlockSwapPurchaser { function swapAndCall( address lock, address srcToken, + uint keyPrice, uint amountInMax, address uniswapRouter, bytes memory swapCalldata, bytes memory callData ) public payable returns (bytes memory) { - // check if lock exists - (bool lockExists, , ) = IUnlock(unlockAddress).locks(lock); - if (!lockExists) { - revert LockDoesntExist(lock); - } + // make sure the lock is registered in Unlock + lockExists(lock); - // make sure if (uniswapRouters[uniswapRouter] != true) { revert UnautorizedRouter(uniswapRouter); } @@ -173,19 +182,19 @@ contract UnlockSwapPurchaser { destToken == address(0) ? getBalance(destToken) - msg.value : getBalance(destToken) - ) < balanceTokenDestBefore + IPublicLock(lock).keyPrice() + ) < balanceTokenDestBefore + keyPrice ) { revert InsufficientBalance(); } // approve ERC20 to call the lock if (destToken != address(0)) { - IMintableERC20(destToken).approve(lock, IPublicLock(lock).keyPrice()); + IMintableERC20(destToken).approve(lock, keyPrice); } // call the lock (bool lockCallSuccess, bytes memory returnData) = lock.call{ - value: destToken == address(0) ? IPublicLock(lock).keyPrice() : 0 + value: destToken == address(0) ? keyPrice : 0 }(callData); if (lockCallSuccess == false) { diff --git a/smart-contracts/test/UnlockSwapPurchaser/usePurchaseHook.mainnet.js b/smart-contracts/test/UnlockSwapPurchaser/usePurchaseHook.mainnet.js new file mode 100644 index 00000000000..ad1e35105a9 --- /dev/null +++ b/smart-contracts/test/UnlockSwapPurchaser/usePurchaseHook.mainnet.js @@ -0,0 +1,240 @@ +const { assert } = require('chai') +const { ethers } = require('hardhat') +const { + getSignatureForPassword, + deployLock, + compareBigNumbers, + MAX_UINT, +} = require('../helpers') + +const { + ADDRESS_ZERO, + addSomeETH, + addERC20, + getUnlock, + getNetwork, + PERMIT2_ADDRESS, + getUniswapTokens, + getUniswapRoute, +} = require('@unlock-protocol/hardhat-helpers') + +let swapPurchaser, unlock, lock, tokenAddress + +let owner, keyOwner +let native, usdc + +// hooks params +const code = 'PROMO CODE' +const recipient = '0xF5C28ce24cf47849988f147d5C75787c0103534'.toLowerCase() +const discount = 3000 // basis points +const cap = 10 + +describe('UnlockSwapPurchaser / purchase with promo code', () => { + before(async () => { + if (!process.env.RUN_FORK) { + // all suite will be skipped + this.skip() + } + ;[owner, keyOwner] = await ethers.getSigners() + + // fund deployer and keyOwner + await addSomeETH(owner.address) + await addSomeETH(keyOwner.address) + + const UnlockSwapPurchaser = await ethers.getContractFactory( + 'UnlockSwapPurchaser' + ) + // use mainnet settings for testing purposes only + const { + unlockAddress, + id: chainId, + uniswapV3: { universalRouterAddress }, + } = await getNetwork(1) + + unlock = await getUnlock(unlockAddress) + + const routers = [ + universalRouterAddress, + '0x3fC91A3afd70395Cd496C647d5a6CC9D4B2b7FAD', + ] + + swapPurchaser = await UnlockSwapPurchaser.deploy( + unlock.address, + PERMIT2_ADDRESS, + routers + ) + // get usdc token for testing + ; ({ native, usdc } = await getUniswapTokens(chainId)) + tokenAddress = usdc.address + + // deploy hook + const DiscountHook = await ethers.getContractFactory('DiscountHook') + const hook = await DiscountHook.deploy() + await hook.deployed() + + const [dataRecipient, signerAddress] = await getSignatureForPassword( + code, + recipient + ) + + // hook works with correct password + assert.equal( + await hook.getSigner(recipient.toLowerCase(), dataRecipient), + signerAddress + ) + + // create a lock + lock = await deployLock({ + unlock, + tokenAddress, + keyPrice: ethers.utils.parseUnits('1', 6), // USDC has 6 decimals, we set 1 USDC + }) + + // set the hook + await lock.setEventHooks( + hook.address, + ethers.constants.AddressZero, + ethers.constants.AddressZero, + ethers.constants.AddressZero, + ethers.constants.AddressZero, + ethers.constants.AddressZero, + ethers.constants.AddressZero + ) + + // price wihtout seetings is correct + compareBigNumbers( + await lock.purchasePriceFor(keyOwner.address, keyOwner.address, []), + await lock.keyPrice() + ) + + // Set the code on the hook for the lock + const [, signer] = await getSignatureForPassword( + code, + keyOwner.address.toLowerCase() + ) + await hook.setSigner(lock.address, signer, discount, cap) + }) + + it.only('price with promo code is correct', async () => { + const [data] = await getSignatureForPassword( + code, + keyOwner.address.toLowerCase() + ) + const price = await lock.purchasePriceFor( + keyOwner.address, + keyOwner.address, + data + ) + assert.equal(ethers.utils.formatUnits(price, 6), '0.7') + }) + + it.skip('can buy tickets at discount', async () => { + // User does not have a key + assert.equal((await lock.balanceOf(keyOwner.address)).toNumber(), 0) + const [data] = await getSignatureForPassword( + code, + keyOwner.address.toLowerCase() + ) + // check the price + const price = await lock.purchasePriceFor( + keyOwner.address, + keyOwner.address, + data + ) + assert.equal(ethers.utils.formatUnits(price, 6), '0.7') + + const token = await lock.tokenAddress() + + // fund! + const tokenContract = await addERC20(token, keyOwner.address, price) + + await tokenContract.connect(keyOwner).approve(lock.address, MAX_UINT) + + // purchase! + await lock + .connect(keyOwner) + .purchase( + [price], + [keyOwner.address], + [keyOwner.address], + [keyOwner.address], + [data], + { + value: price, + } + ) + assert.equal((await lock.balanceOf(keyOwner.address)).toNumber(), 1) + }) + + it.only('use promocode when swap and purchase', async () => { + // a user does have a key + assert.equal((await lock.balanceOf(keyOwner.address)).toNumber(), 0) + const [data] = await getSignatureForPassword( + code, + keyOwner.address.toLowerCase() + ) + // check the price + const price = await lock.purchasePriceFor( + keyOwner.address, + keyOwner.address, + data + ) + assert.equal(ethers.utils.formatUnits(price, 6), '0.7') + + const args = [ + [price], // keyPrices + [keyOwner.address], // recipients + [ADDRESS_ZERO], + [ADDRESS_ZERO], + [data], // _data + ] + + // parse call data + const calldata = await lock.interface.encodeFunctionData('purchase', args) + + const { swapCalldata, value, swapRouter, amountInMax } = + await getUniswapRoute({ + tokenIn: native, + tokenOut: usdc, + amoutOut: price, + recipient: swapPurchaser.address, + chainId: 1, + }) + + const token = await lock.tokenAddress() + const tokenContract = await addERC20(token, keyOwner.address, price) + console.log('APPROVAL') + console.log(`- contract: ${tokenContract.address}`) + console.log(`- approver: ${keyOwner.address}`) + console.log(`- approved: ${swapPurchaser.address}`) + console.log(`- amount : ${MAX_UINT}`) + await tokenContract + .connect(keyOwner) + .approve(swapPurchaser.address, MAX_UINT) + console.log('APPROVAL DONE') + + console.log(await tokenContract.balanceOf(keyOwner.address)) + console.log( + await tokenContract.allowance(keyOwner.address, swapPurchaser.address) + ) + + // WHY DOES THIS FAIL? + await tokenContract + .connect(keyOwner) + .transferFrom(keyOwner.address, swapPurchaser.address, 1) + + console.log('TRANSFERED') + + // do the swap and call! + await swapPurchaser.connect(keyOwner).swapAndCall( + lock.address, + tokenAddress, + amountInMax, // value in src token + swapRouter, + swapCalldata, + calldata, + { value } + ) + assert.equal((await lock.balanceOf(keyOwner.address)).toNumber(), 1) + }) +}) diff --git a/smart-contracts/test/helpers/password.js b/smart-contracts/test/helpers/password.js new file mode 100644 index 00000000000..b6000d0bc8d --- /dev/null +++ b/smart-contracts/test/helpers/password.js @@ -0,0 +1,28 @@ +const { ethers } = require('hardhat') + +/** + * Helper function + * @param {*} password + * @param {*} message + * @returns + */ +const getSignatureForPassword = async (password, message) => { + // Build the signer + const encoded = ethers.utils.defaultAbiCoder.encode( + ['bytes32'], + [ethers.utils.id(password)] + ) + const privateKey = ethers.utils.keccak256(encoded) + const privateKeyAccount = new ethers.Wallet(privateKey) + + // Sign + const messageHash = ethers.utils.solidityKeccak256(['string'], [message]) + const messageHashBinary = ethers.utils.arrayify(messageHash) + const signature = await privateKeyAccount.signMessage(messageHashBinary) + + return [signature, privateKeyAccount.address] +} + +module.exports = { + getSignatureForPassword, +} diff --git a/unlock-app/src/hooks/useUniswapRoutes.ts b/unlock-app/src/hooks/useUniswapRoutes.ts index a91cbc48734..dd19361893c 100644 --- a/unlock-app/src/hooks/useUniswapRoutes.ts +++ b/unlock-app/src/hooks/useUniswapRoutes.ts @@ -41,6 +41,7 @@ export const useUniswapRoutes = ({ ['uniswapRoutes', account, lock, recipients, purchaseData], async () => { const networkConfig = networks[lock.network] + console.log(networkConfig) if (!networkConfig || !networkConfig.swapPurchaser) { return [] } @@ -126,40 +127,42 @@ export const useUniswapRoutes = ({ route.tokenIn!.address.toLowerCase() ) }) + console.log(routesToLookup) const result = await Promise.all( routesToLookup.map(async (route: UniswapRoute) => { - try { - const params = { - network: route.network, - tokenIn: route.tokenIn, - tokenOut: route.tokenOut, - amountOut: route.amountOut, - recipient: route.recipient, - } - const response: UnlockUniswapRoute = - await web3Service.getUniswapRoute({ - params, - }) + // try { + const params = { + network: route.network, + tokenIn: route.tokenIn, + tokenOut: route.tokenOut, + amountOut: route.amountOut, + recipient: route.recipient, + } + const response: UnlockUniswapRoute = + await web3Service.getUniswapRoute({ + params, + }) - const balance = await getAccountTokenBalance( - web3Service, - account!, - route.tokenIn instanceof Token ? route.tokenIn.address : null, - route.network + console.log(response) + const balance = await getAccountTokenBalance( + web3Service, + account!, + route.tokenIn instanceof Token ? route.tokenIn.address : null, + route.network + ) + // If the balance is less than the quote, we cannot make the swap. + if (Number(balance) < Number(response.quote.toFixed())) { + console.log( + `Insufficient balance of ${response.quote.currency.symbol}` ) - // If the balance is less than the quote, we cannot make the swap. - if (Number(balance) < Number(response.quote.toFixed())) { - console.log( - `Insufficient balance of ${response.quote.currency.symbol}` - ) - return null - } - return response - } catch (error) { - console.error(error) return null } + return response + // } catch (error) { + // console.error(error) + // return null + // } }) ) return result.filter((item) => !!item) diff --git a/yarn.lock b/yarn.lock index 65ce52916c6..8069fc948e0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17916,6 +17916,15 @@ __metadata: languageName: node linkType: hard +"@types/brotli@npm:^1.3.4": + version: 1.3.4 + resolution: "@types/brotli@npm:1.3.4" + dependencies: + "@types/node": "npm:*" + checksum: 10/4ff49c2cefb40d6e745e5b4e110c12587fc8f25a6c71220b10f60406ff9905dbf21d796180d1bfbdb266d98b73d8947a734597560c56b9d70432963d7301ffa5 + languageName: node + linkType: hard + "@types/cacheable-request@npm:^6.0.1, @types/cacheable-request@npm:^6.0.2": version: 6.0.3 resolution: "@types/cacheable-request@npm:6.0.3" @@ -19481,7 +19490,7 @@ __metadata: languageName: node linkType: hard -"@uniswap/default-token-list@npm:^11.2.0": +"@uniswap/default-token-list@npm:^11.13.0, @uniswap/default-token-list@npm:^11.2.0": version: 11.15.0 resolution: "@uniswap/default-token-list@npm:11.15.0" checksum: 10/87fdd00fc28940c1dfbad85dbf9836e29fd4460e787af59cfb16782dd15ac2e8d3f5e3b75c0fb1334772c5291505321b59c14c250f6fb7b95f571fc19b145a0b @@ -19525,6 +19534,19 @@ __metadata: languageName: node linkType: hard +"@uniswap/router-sdk@npm:^1.9.0": + version: 1.9.0 + resolution: "@uniswap/router-sdk@npm:1.9.0" + dependencies: + "@ethersproject/abi": "npm:^5.5.0" + "@uniswap/sdk-core": "npm:^4.2.0" + "@uniswap/swap-router-contracts": "npm:^1.1.0" + "@uniswap/v2-sdk": "npm:^4.3.0" + "@uniswap/v3-sdk": "npm:^3.11.0" + checksum: 10/45af379ce7c1fb5fb43c7b6e57a664ea7bb4eeebfa09c73a3fe50cfc31abdfe1453a89bb955d08972cd8a2767d5cdcdc113143a3a5aa6115c95f228177e82569 + languageName: node + linkType: hard + "@uniswap/sdk-core@npm:4.0.9": version: 4.0.9 resolution: "@uniswap/sdk-core@npm:4.0.9" @@ -19539,6 +19561,20 @@ __metadata: languageName: node linkType: hard +"@uniswap/sdk-core@npm:4.2.0, @uniswap/sdk-core@npm:^4.2.0": + version: 4.2.0 + resolution: "@uniswap/sdk-core@npm:4.2.0" + dependencies: + "@ethersproject/address": "npm:^5.0.2" + big.js: "npm:^5.2.2" + decimal.js-light: "npm:^2.5.0" + jsbi: "npm:^3.1.4" + tiny-invariant: "npm:^1.1.0" + toformat: "npm:^2.0.0" + checksum: 10/8a0d2dc1ddf6f96413be7f3cd707f815eaa6861625b3befa4af9818508c3066933455754a90022498770a4321e6642420d1ab3f9bba1ed9ef2f35e1cc71d3621 + languageName: node + linkType: hard + "@uniswap/sdk-core@npm:^4.0.7, @uniswap/sdk-core@npm:^4.1.3": version: 4.1.4 resolution: "@uniswap/sdk-core@npm:4.1.4" @@ -19585,23 +19621,25 @@ __metadata: languageName: node linkType: hard -"@uniswap/smart-order-router@npm:3.19.2": - version: 3.19.2 - resolution: "@uniswap/smart-order-router@npm:3.19.2" +"@uniswap/smart-order-router@npm:3.25.0": + version: 3.25.0 + resolution: "@uniswap/smart-order-router@npm:3.25.0" dependencies: - "@uniswap/default-token-list": "npm:^11.2.0" + "@types/brotli": "npm:^1.3.4" + "@uniswap/default-token-list": "npm:^11.13.0" "@uniswap/permit2-sdk": "npm:^1.2.0" - "@uniswap/router-sdk": "npm:^1.6.0" - "@uniswap/sdk-core": "npm:^4.0.7" - "@uniswap/swap-router-contracts": "npm:^1.3.0" + "@uniswap/router-sdk": "npm:^1.9.0" + "@uniswap/sdk-core": "npm:^4.2.0" + "@uniswap/swap-router-contracts": "npm:^1.3.1" "@uniswap/token-lists": "npm:^1.0.0-beta.31" - "@uniswap/universal-router": "npm:^1.0.1" - "@uniswap/universal-router-sdk": "npm:^1.5.8" - "@uniswap/v2-sdk": "npm:^3.2.3" - "@uniswap/v3-sdk": "npm:^3.10.0" + "@uniswap/universal-router": "npm:^1.6.0" + "@uniswap/universal-router-sdk": "npm:^1.8.1" + "@uniswap/v2-sdk": "npm:^4.3.0" + "@uniswap/v3-sdk": "npm:^3.11.0" async-retry: "npm:^1.3.1" await-timeout: "npm:^1.1.1" axios: "npm:^0.21.1" + brotli: "npm:^1.3.3" bunyan: "npm:^1.8.15" bunyan-blackhole: "npm:^1.1.1" ethers: "npm:^5.7.2" @@ -19613,11 +19651,11 @@ __metadata: stats-lite: "npm:^2.2.0" peerDependencies: jsbi: ^3.2.0 - checksum: 10/95c705790d51a6e54e4cfbdfe23bdb302b68e84c3e0d482c112edfd7d0683d6dad5b84ab0d81ca6dfe64f84bb0f54ff6349c9c2b4519b6ecd10e2e6bc0ee3b7d + checksum: 10/46e10b0667d93ca8d9382fa74cc516d340872be04f2000f79606b800e8367ca124858e89dd791e6d78f8701ea96e22e8d8dd59fb81b8f40ab7b752fc067e4782 languageName: node linkType: hard -"@uniswap/swap-router-contracts@npm:^1.1.0, @uniswap/swap-router-contracts@npm:^1.2.1, @uniswap/swap-router-contracts@npm:^1.3.0": +"@uniswap/swap-router-contracts@npm:^1.1.0, @uniswap/swap-router-contracts@npm:^1.2.1, @uniswap/swap-router-contracts@npm:^1.3.0, @uniswap/swap-router-contracts@npm:^1.3.1": version: 1.3.1 resolution: "@uniswap/swap-router-contracts@npm:1.3.1" dependencies: @@ -19654,7 +19692,23 @@ __metadata: languageName: node linkType: hard -"@uniswap/universal-router@npm:1.6.0": +"@uniswap/universal-router-sdk@npm:^1.8.1": + version: 1.8.1 + resolution: "@uniswap/universal-router-sdk@npm:1.8.1" + dependencies: + "@uniswap/permit2-sdk": "npm:^1.2.0" + "@uniswap/router-sdk": "npm:^1.9.0" + "@uniswap/sdk-core": "npm:^4.2.0" + "@uniswap/universal-router": "npm:1.6.0" + "@uniswap/v2-sdk": "npm:^4.2.0" + "@uniswap/v3-sdk": "npm:^3.11.0" + bignumber.js: "npm:^9.0.2" + ethers: "npm:^5.3.1" + checksum: 10/8ebacfe8230d592d07228f28f2974d242707d8324dc3f0170c0564c7ee55297fd20925d0a3a2fe6e861a8bea7f26b20e78e85c9a4874b9da5ccb5dc56f3816c0 + languageName: node + linkType: hard + +"@uniswap/universal-router@npm:1.6.0, @uniswap/universal-router@npm:^1.6.0": version: 1.6.0 resolution: "@uniswap/universal-router@npm:1.6.0" dependencies: @@ -19726,6 +19780,19 @@ __metadata: languageName: node linkType: hard +"@uniswap/v2-sdk@npm:^4.2.0, @uniswap/v2-sdk@npm:^4.3.0": + version: 4.3.0 + resolution: "@uniswap/v2-sdk@npm:4.3.0" + dependencies: + "@ethersproject/address": "npm:^5.0.0" + "@ethersproject/solidity": "npm:^5.0.0" + "@uniswap/sdk-core": "npm:^4.2.0" + tiny-invariant: "npm:^1.1.0" + tiny-warning: "npm:^1.0.3" + checksum: 10/8bdb246e5c253779104cd308a22a7f678456a5c90ec3a34738e8e471ff8da322ebed953827af13d1dda43559813e71297371e2941cb14ec2b0eae9fa571f4d86 + languageName: node + linkType: hard + "@uniswap/v3-core@npm:1.0.0": version: 1.0.0 resolution: "@uniswap/v3-core@npm:1.0.0" @@ -19753,7 +19820,7 @@ __metadata: languageName: node linkType: hard -"@uniswap/v3-sdk@npm:3.10.2, @uniswap/v3-sdk@npm:^3.10.0, @uniswap/v3-sdk@npm:^3.10.1": +"@uniswap/v3-sdk@npm:^3.10.0, @uniswap/v3-sdk@npm:^3.10.1": version: 3.10.2 resolution: "@uniswap/v3-sdk@npm:3.10.2" dependencies: @@ -19769,6 +19836,22 @@ __metadata: languageName: node linkType: hard +"@uniswap/v3-sdk@npm:^3.11.0": + version: 3.11.0 + resolution: "@uniswap/v3-sdk@npm:3.11.0" + dependencies: + "@ethersproject/abi": "npm:^5.0.12" + "@ethersproject/solidity": "npm:^5.0.9" + "@uniswap/sdk-core": "npm:^4.2.0" + "@uniswap/swap-router-contracts": "npm:^1.2.1" + "@uniswap/v3-periphery": "npm:^1.1.1" + "@uniswap/v3-staker": "npm:1.0.0" + tiny-invariant: "npm:^1.1.0" + tiny-warning: "npm:^1.0.3" + checksum: 10/6bd4738ffa25f8a6d6c77ea4d5928483c69c73789ab87b1b48c33377a4765b6fcd337a6ca09bd7f346c17191e49adc36e64fd604aaf15aed5d275ce232047300 + languageName: node + linkType: hard + "@uniswap/v3-staker@npm:1.0.0": version: 1.0.0 resolution: "@uniswap/v3-staker@npm:1.0.0" @@ -19939,15 +20022,15 @@ __metadata: "@nomiclabs/hardhat-ethers": "npm:2.2.3" "@nomiclabs/hardhat-waffle": "npm:2.0.6" "@uniswap/permit2-sdk": "npm:1.2.0" - "@uniswap/sdk-core": "npm:4.0.9" - "@uniswap/smart-order-router": "npm:3.19.2" - "@uniswap/v3-sdk": "npm:3.10.2" + "@uniswap/sdk-core": "npm:4.2.0" + "@uniswap/smart-order-router": "npm:3.25.0" "@unlock-protocol/contracts": "workspace:^" "@unlock-protocol/networks": "workspace:^" "@unlock-protocol/tsconfig": "workspace:^" "@unlock-protocol/types": "workspace:^" copyfiles: "npm:2.4.1" ethers: "npm:6.10.0" + ethersv5: "npm:ethers@^5.7.2" hardhat: "npm:2.20.1" tsup: "npm:8.0.2" typescript: "npm:5.3.3" @@ -23910,7 +23993,7 @@ __metadata: languageName: node linkType: hard -"base64-js@npm:^1.0.2, base64-js@npm:^1.3.1": +"base64-js@npm:^1.0.2, base64-js@npm:^1.1.2, base64-js@npm:^1.3.1": version: 1.5.1 resolution: "base64-js@npm:1.5.1" checksum: 10/669632eb3745404c2f822a18fc3a0122d2f9a7a13f7fb8b5823ee19d1d2ff9ee5b52c53367176ea4ad093c332fd5ab4bd0ebae5a8e27917a4105a4cfc86b1005 @@ -24424,6 +24507,15 @@ __metadata: languageName: node linkType: hard +"brotli@npm:^1.3.3": + version: 1.3.3 + resolution: "brotli@npm:1.3.3" + dependencies: + base64-js: "npm:^1.1.2" + checksum: 10/78b412f54be3c96b86e2d9805ddc26aa5a52bba45588ff7f8468b80aa84c90052c60eeb2e26ad032c39bab6baa58e0b0625cf4f738279961a31c34cbe4b4b490 + languageName: node + linkType: hard + "browser-assert@npm:^1.2.1": version: 1.2.1 resolution: "browser-assert@npm:1.2.1" @@ -30957,7 +31049,7 @@ __metadata: languageName: node linkType: hard -"ethers@npm:5.7.2, ethers@npm:^5.3.1, ethers@npm:^5.5.4, ethers@npm:^5.6.1, ethers@npm:^5.7.0, ethers@npm:^5.7.1, ethers@npm:^5.7.2": +"ethers@npm:5.7.2, ethers@npm:^5.3.1, ethers@npm:^5.5.4, ethers@npm:^5.6.1, ethers@npm:^5.7.0, ethers@npm:^5.7.1, ethers@npm:^5.7.2, ethersv5@npm:ethers@^5.7.2": version: 5.7.2 resolution: "ethers@npm:5.7.2" dependencies: