Skip to content

Commit 425f6bc

Browse files
committed
feat: implement AgentTradingModule with initial order validation
Add constructor and setUp initializer with required dependencies Implement initial setOrderTradeable function with core validations Remove abstract template in favor of concrete implementation
1 parent d52a50f commit 425f6bc

File tree

1 file changed

+57
-14
lines changed

1 file changed

+57
-14
lines changed

cow-trader/contracts/AgentTradingModule.sol

Lines changed: 57 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,65 @@ pragma solidity 0.8.25;
44
import {Enum} from "./dependencies/@gnosis.pm/safe-contracts/contracts/common/Enum.sol";
55
import {Module} from "./dependencies/@gnosis-guild/zodiac/contracts/core/Module.sol";
66
import {IAvatar} from "./dependencies/@gnosis-guild/zodiac/contracts/interfaces/IAvatar.sol";
7+
import {GPv2Order} from "./dependencies/cowprotocol/contracts/src/contracts/libraries/GPv2Order.sol";
8+
import {ITokenAllowlist} from "./interfaces/ITokenAllowlist.sol";
79

8-
abstract contract AgentTradingModule is Module {
9-
function exec(address to, uint256 value, bytes memory data, Enum.Operation operation)
10-
internal
11-
override
12-
returns (bool success)
13-
{
14-
success = IAvatar(target).execTransactionFromModule(to, value, data, operation);
10+
contract AgentTradingModule is Module {
11+
using GPv2Order for bytes;
12+
13+
event SetOrderTradeable(
14+
bytes indexed orderUid,
15+
address indexed sellToken,
16+
address indexed buyToken,
17+
uint256 sellAmount,
18+
uint256 buyAmount
19+
);
20+
21+
ITokenAllowlist internal allowlist;
22+
bytes32 internal domainSeparator;
23+
24+
constructor(address _owner, address _avatar, address _target, address _tokenAllowlist, bytes32 _domainSeparator) {
25+
bytes memory initParams = abi.encode(_owner, _avatar, _target, _tokenAllowlist, _domainSeparator);
26+
setUp(initParams);
27+
}
28+
29+
function setUp(bytes memory initParams) public override initializer {
30+
(address _owner, address _avatar, address _target, address _tokenAllowlist, bytes32 _domainSeparator) =
31+
abi.decode(initParams, (address, address, address, address, bytes32));
32+
33+
require(_avatar != address(0));
34+
require(_target != address(0));
35+
36+
__Ownable_init(msg.sender);
37+
38+
setAvatar(_avatar);
39+
setTarget(_target);
40+
allowlist = ITokenAllowlist(_tokenAllowlist);
41+
domainSeparator = _domainSeparator;
42+
43+
transferOwnership(_owner);
1544
}
1645

17-
function execAndReturnData(address to, uint256 value, bytes memory data, Enum.Operation operation)
18-
internal
19-
virtual
20-
override
21-
returns (bool success, bytes memory returnData)
22-
{
23-
(success, returnData) = IAvatar(target).execTransactionFromModuleReturnData(to, value, data, operation);
46+
function setOrderTradeable(bytes memory orderUid, GPv2Order.Data memory order) external {
47+
bytes memory uid;
48+
uid.packOrderUidParams(GPv2Order.hash(order, domainSeparator), owner(), order.validTo);
49+
50+
// Order UID validation
51+
require(keccak256(orderUid) == keccak256(uid));
52+
53+
// Order tokens validation
54+
require(allowlist.isOrderAllowed(address(order.sellToken), address(order.buyToken)));
55+
56+
// @todo validation:
57+
// - balances
58+
// - paused
59+
// - trade frequency
60+
61+
bytes memory data = abi.encodeWithSignature("setPreSignature(bytes,bool)", orderUid, true);
62+
require(exec(address(allowlist), 0, data, Enum.Operation.Call));
63+
64+
emit SetOrderTradeable(
65+
orderUid, address(order.sellToken), address(order.buyToken), order.sellAmount, order.buyAmount
66+
);
2467
}
2568
}

0 commit comments

Comments
 (0)