Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: intent-based settlement Settler #227

Draft
wants to merge 14 commits into
base: master
Choose a base branch
from
Draft
Next Next commit
WIP: intent-based settlement Settler
duncancmt committed Aug 28, 2024
commit 584e4d677d4b5f3f2fffd3e927cce45b34fcf7b4
6 changes: 5 additions & 1 deletion src/Settler.sol
Original file line number Diff line number Diff line change
@@ -21,7 +21,11 @@ abstract contract Settler is Permit2PaymentTakerSubmitted, SettlerBase {
// When/if you change this, you must make corresponding changes to
// `sh/deploy_new_chain.sh` and 'sh/common_deploy_settler.sh' to set
// `constructor_args`.
constructor(bytes20 gitCommit) SettlerBase(gitCommit, 2) {}
constructor(bytes20 gitCommit) SettlerBase(gitCommit) {}

function _tokenId() internal pure override returns (uint256) {
return 2;
}

function _hasMetaTxn() internal pure override returns (bool) {
return false;
7 changes: 7 additions & 0 deletions src/SettlerAbstract.sol
Original file line number Diff line number Diff line change
@@ -9,13 +9,20 @@ abstract contract SettlerAbstract is Permit2PaymentAbstract {
"SlippageAndActions(address recipient,address buyToken,uint256 minAmountOut,bytes[] actions)";
bytes32 internal constant SLIPPAGE_AND_ACTIONS_TYPEHASH =
0x615e8d716cef7295e75dd3f1f10d679914ad6d7759e8e9459f0109ef75241701;
// Permit2 Witness for intents
string internal constant SLIPPAGE_TYPE = "Slippage(address recipient,address buyToken,uint256 minAmountOut)";
bytes32 internal constant SLIPPAGE_TYPEHASH = 0xdc83993a2ffc65b01b71ed08790b6e39c5c55d76937b62a3b5085b02071f1259;

uint256 internal constant BASIS = 10_000;

constructor() {
assert(SLIPPAGE_AND_ACTIONS_TYPEHASH == keccak256(bytes(SLIPPAGE_AND_ACTIONS_TYPE)));
assert(SLIPPAGE_TYPEHASH == keccak256(bytes(SLIPPAGE_TYPE)));
}

function _hasMetaTxn() internal pure virtual returns (bool);

function _tokenId() internal pure virtual returns (uint256);

function _dispatch(uint256 i, bytes4 action, bytes calldata data) internal virtual returns (bool);
}
4 changes: 2 additions & 2 deletions src/SettlerBase.sol
Original file line number Diff line number Diff line change
@@ -57,10 +57,10 @@ abstract contract SettlerBase is Basic, RfqOrderSettlement, UniswapV3Fork, Unisw

event GitCommit(bytes20 indexed);

constructor(bytes20 gitCommit, uint256 tokenId) {
constructor(bytes20 gitCommit) {
if (block.chainid != 31337) {
emit GitCommit(gitCommit);
assert(IERC721Owner(0x00000000000004533Fe15556B1E086BB1A72cEae).ownerOf(tokenId) == address(this));
assert(IERC721Owner(0x00000000000004533Fe15556B1E086BB1A72cEae).ownerOf(_tokenId()) == address(this));
} else {
assert(gitCommit == bytes20(0));
}
62 changes: 62 additions & 0 deletions src/SettlerIntent.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;

import {SettlerAbstract} from "./SettlerAbstract.sol";
import {SettlerBase} from "./SettlerBase.sol";
import {SettlerMetaTxn} from "./SettlerMetaTxn.sol";

import {Permit2PaymentIntent, Permit2PaymentMetaTxn} from "./core/Permit2Payment.sol";

abstract contract SettlerIntent is Permit2PaymentIntent, SettlerMetaTxn {
// When/if you change this, you must make corresponding changes to
// `sh/deploy_new_chain.sh` and 'sh/common_deploy_settler.sh' to set
// `constructor_args`.
constructor(bytes20 gitCommit) SettlerMetaTxn(gitCommit) {}

function _tokenId() internal pure override(SettlerAbstract, SettlerMetaTxn) returns (uint256) {
return 4;
}

function _msgSender()
internal
view
virtual
// Solidity inheritance is so stupid
override(Permit2PaymentMetaTxn, SettlerMetaTxn)
returns (address)
{
return super._msgSender();
}

// Solidity inheritance is so stupid
function _witnessTypeSuffix() internal pure override(Permit2PaymentMetaTxn, Permit2PaymentIntent) returns (string memory) {
return super._witnessTypeSuffix();
}

function _hashSlippage(AllowedSlippage calldata slippage)
internal
pure
returns (bytes32 result)
{
// This function does not check for or clean any dirty bits that might
// exist in `slippage`. We assume that `slippage` will be used elsewhere
// in this context and that if there are dirty bits it will result in a
// revert later.
assembly ("memory-safe") {
let ptr := mload(0x40)
mstore(ptr, SLIPPAGE_TYPEHASH)
calldatacopy(add(ptr, 0x20), slippage, 0x60)
result := keccak256(ptr, 0x80)
}
}

function _executeMetaTxn(
AllowedSlippage calldata slippage,
bytes[] calldata actions,
bytes32, /* zid & affiliate */
address msgSender,
bytes calldata sig
) public virtual metaTx(msgSender, _hashSlippage(slippage)) returns (bool) {
return _executeMetaTxn(slippage, actions, sig);
}
}
22 changes: 17 additions & 5 deletions src/SettlerMetaTxn.sol
Original file line number Diff line number Diff line change
@@ -19,7 +19,11 @@ abstract contract SettlerMetaTxn is Permit2PaymentMetaTxn, SettlerBase {
// When/if you change this, you must make corresponding changes to
// `sh/deploy_new_chain.sh` and 'sh/common_deploy_settler.sh' to set
// `constructor_args`.
constructor(bytes20 gitCommit) SettlerBase(gitCommit, 3) {}
constructor(bytes20 gitCommit) SettlerBase(gitCommit) {}

function _tokenId() internal pure virtual override returns (uint256) {
return 3;
}

function _hasMetaTxn() internal pure override returns (bool) {
return true;
@@ -122,13 +126,11 @@ abstract contract SettlerMetaTxn is Permit2PaymentMetaTxn, SettlerBase {
return true;
}

function executeMetaTxn(
function _executeMetaTxn(
AllowedSlippage calldata slippage,
bytes[] calldata actions,
bytes32, /* zid & affiliate */
address msgSender,
bytes calldata sig
) public metaTx(msgSender, _hashActionsAndSlippage(actions, slippage)) returns (bool) {
) internal returns (bool) {
require(actions.length != 0);
{
(bytes4 action, bytes calldata data) = actions.decodeCall(0);
@@ -151,4 +153,14 @@ abstract contract SettlerMetaTxn is Permit2PaymentMetaTxn, SettlerBase {
_checkSlippageAndTransfer(slippage);
return true;
}

function executeMetaTxn(
AllowedSlippage calldata slippage,
bytes[] calldata actions,
bytes32, /* zid & affiliate */
address msgSender,
bytes calldata sig
) public virtual metaTx(msgSender, _hashActionsAndSlippage(actions, slippage)) returns (bool) {
return _executeMetaTxn(slippage, actions, sig);
}
}
22 changes: 14 additions & 8 deletions src/core/Permit2Payment.sol
Original file line number Diff line number Diff line change
@@ -367,13 +367,11 @@ abstract contract Permit2PaymentMetaTxn is Context, Permit2Payment {
return Permit2PaymentBase._msgSender();
}

// `string.concat` isn't recognized by solc as compile-time constant, but `abi.encodePacked` is
// This is defined here as `private` and not in `SettlerAbstract` as `internal` because no other
// contract/file should reference it. The *ONLY* approved way to make a transfer using this
// witness string is by setting the witness with modifier `metaTx`
string private constant _SLIPPAGE_AND_ACTIONS_WITNESS = string(
abi.encodePacked("SlippageAndActions slippageAndActions)", SLIPPAGE_AND_ACTIONS_TYPE, TOKEN_PERMISSIONS_TYPE)
);
function _witnessTypeSuffix() internal pure virtual returns (string memory) {
return string(
abi.encodePacked("SlippageAndActions slippageAndActions)", SLIPPAGE_AND_ACTIONS_TYPE, TOKEN_PERMISSIONS_TYPE)
);
}

function _transferFrom(
ISignatureTransfer.PermitTransferFrom memory permit,
@@ -386,7 +384,7 @@ abstract contract Permit2PaymentMetaTxn is Context, Permit2Payment {
revert ConfusedDeputy();
}
_transferFromIKnowWhatImDoing(
permit, transferDetails, _msgSender(), witness, _SLIPPAGE_AND_ACTIONS_WITNESS, sig, isForwarded
permit, transferDetails, _msgSender(), witness, _witnessTypeSuffix(), sig, isForwarded
);
}

@@ -412,3 +410,11 @@ abstract contract Permit2PaymentMetaTxn is Context, Permit2Payment {
TransientStorage.checkSpentWitness();
}
}

abstract contract Permit2PaymentIntent is Permit2PaymentMetaTxn {
function _witnessTypeSuffix() internal pure virtual override returns (string memory) {
return string(
abi.encodePacked("Slippage slippage)", SLIPPAGE_TYPE, TOKEN_PERMISSIONS_TYPE)
);
}
}
4 changes: 4 additions & 0 deletions test/unit/core/BasicUnitTest.t.sol
Original file line number Diff line number Diff line change
@@ -15,6 +15,10 @@ contract BasicDummy is Permit2PaymentTakerSubmitted, Basic {
super.basicSellToPool(sellToken, bps, pool, offset, data);
}

function _tokenId() internal pure override returns (uint256) {
revert("unimplemented");
}

function _hasMetaTxn() internal pure override returns (bool) {
return false;
}
4 changes: 4 additions & 0 deletions test/unit/core/MakerPSMUnitTest.t.sol
Original file line number Diff line number Diff line change
@@ -23,6 +23,10 @@ contract MakerPSMDummy is MakerPSM {
revert("unimplemented");
}

function _tokenId() internal pure override returns (uint256) {
revert("unimplemented");
}

function _hasMetaTxn() internal pure override returns (bool) {
revert("unimplemented");
}
4 changes: 4 additions & 0 deletions test/unit/core/RfqUnitTest.t.sol
Original file line number Diff line number Diff line change
@@ -31,6 +31,10 @@ abstract contract RfqOrderSettlementDummyBase is RfqOrderSettlement, Permit2Paym
)
);
}

function _tokenId() internal pure override returns (uint256) {
revert("unimplemented");
}
}

contract RfqOrderSettlementDummy is Permit2PaymentTakerSubmitted, RfqOrderSettlementDummyBase {
4 changes: 4 additions & 0 deletions test/unit/core/UniswapV2UnitTest.t.sol
Original file line number Diff line number Diff line change
@@ -26,6 +26,10 @@ contract UniswapV2Dummy is Permit2PaymentTakerSubmitted, UniswapV2 {
return false;
}

function _tokenId() internal pure override returns (uint256) {
revert("unimplemented");
}

function _dispatch(uint256, bytes4, bytes calldata) internal pure override returns (bool) {
revert("unimplemented");
}
4 changes: 4 additions & 0 deletions test/unit/core/UniswapV3UnitTest.t.sol
Original file line number Diff line number Diff line change
@@ -23,6 +23,10 @@ contract UniswapV3Dummy is Permit2PaymentTakerSubmitted, UniswapV3Fork {
uniFactory = _uniFactory;
}

function _tokenId() internal pure override returns (uint256) {
revert("unimplemented");
}

function sellSelf(address recipient, uint256 bps, bytes memory encodedPath, uint256 minBuyAmount)
external
takerSubmitted