1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#![allow(clippy::too_many_arguments)]
use alloy_sol_types::sol;
sol! {
/// Cross-chain spend specification used for identity hashing.
#[derive(Default, Debug, PartialEq, Eq, Hash)]
struct SpendSpec {
bytes32 srcSpender;
uint32 srcDomain;
bytes32 srcToken;
bytes32 srcDepositContract;
uint32 dstDomain;
bytes32 dstToken;
bytes32 dstDeliveryContract;
bytes32 dstRecipient;
bytes32 dstCaller;
uint256 amount;
bytes32 salt;
}
/// EIP-712 typed struct matching the Solidity `SpendIntent`.
#[derive(Default, Debug, PartialEq, Eq, Hash)]
struct SpendIntent {
uint256 maxFee;
uint256 expiryHeight;
SpendSpec spec;
}
/// Signed payload authorizing one `TridentDelivery` execution.
///
/// `expiryHeight` is an exclusive upper bound:
/// the attestation is valid only while the destination contract's
/// chain-specific block clock is less than `expiryHeight`.
#[derive(Default, Debug, PartialEq, Eq, Hash)]
struct SpendAttestation {
SpendSpec spec;
uint256 expiryHeight;
uint8 liquidityPath;
bytes liquidityPathData;
}
/// Spender/depositor-facing subset of the `TridentDeposits` contract ABI.
#[sol(rpc, all_derives)]
contract TridentDeposits {
error ZeroAmount();
error InvalidClaimDomain();
error InvalidClaimDepositContract();
error InvalidClaimAmount();
error InvalidSpendIntentSigner();
error ClaimSpendSpecHashAlreadyUsed(bytes32 hash);
error SpendIntentExpired();
error UnsupportedToken(address token);
error EnforcedPause();
event Deposit(address indexed depositor, address indexed token, uint256 amount);
event DepositClaimed(
bytes32 indexed spendSpecHash,
address indexed token,
uint256 amount,
address indexed recipient,
address signer,
uint256 fee,
address feeCollector
);
event DepositBalanceDeficit(
address indexed depositor,
address indexed token,
bytes32 indexed spendSpecHash,
uint256 claimAmount,
uint256 fee,
uint256 availableBalance
);
/// Deposits a supported token into `TridentDeposits`.
function deposit(address token, uint256 amount) external;
/// Returns whether `token` is currently depositable on this deployment.
function isTokenSupported(address token) external view returns (bool);
/// Returns the current supported-token allowlist for this deployment.
function getSupportedTokens() external view returns (address[] memory);
/// Returns the source-side balance tracked in `TridentDeposits` for `depositor` and `token`.
///
/// This is the contract's own reimbursement ledger after processed claims.
/// It is not the delivery-service balance returned by `TridentClient::get_balance`,
/// and it is not a projected or attested amount.
function depositedAmount(address depositor, address token) external view returns (uint256);
/// Returns whether `spendSpecHash` has already been consumed on the source-side contract.
function usedSpendSpecHashes(bytes32 spendSpecHash) external view returns (bool);
/// Returns the source domain this deployment is configured for.
function domain() external view returns (uint32);
/// Returns the paired `TridentDelivery` contract address for this domain.
function tridentDelivery() external view returns (address);
/// Returns the configured withdrawal delay in blocks.
function withdrawalDelay() external view returns (uint256);
/// Returns the current source-side fee collector.
function feeCollector() external view returns (address);
/// Returns the EIP-712 struct hash for `intent`.
function spendIntentStructHash(SpendIntent calldata intent) external pure returns (bytes32);
/// Returns the EIP-712 digest a source spender signs for `intent`.
function spendIntentDigest(SpendIntent calldata intent) external pure returns (bytes32);
/// Recovers the signer of `intent` from its EIP-712 signature.
function recoverSpendIntentSigner(SpendIntent calldata intent, bytes calldata signature)
external
pure
returns (address);
}
/// Spender/depositor-facing subset of the `TridentDelivery` contract ABI.
#[sol(rpc, all_derives)]
contract TridentDelivery {
error InvalidAttestationDomain();
error InvalidAttestationCaller();
error InvalidAttestationRecipient();
error InvalidAttestationDeliveryContract();
error InvalidAttestationAmount();
error InvalidAttestationExpired();
error InvalidAttestationToken();
error AttestationSpendSpecHashAlreadyUsed(bytes32 hash);
error InvalidLiquidityPath();
error NotSameChainSpend();
error TridentDepositsNotSet();
error InvalidAttestationSigner();
error UnsupportedToken(address token);
error EnforcedPause();
event SpendAttestationProcessed(
bytes32 indexed spendSpecHash,
address indexed token,
uint256 amount,
uint256 usdcMinted,
address indexed signer
);
/// Executes a signed spend attestation.
function tridentSpend(bytes calldata attestation, bytes calldata signature) external;
/// Validates `attestation` against the destination contract's current state.
///
/// This is useful for preflight simulation before sending `tridentSpend`.
function validateSpendAttestation(bytes calldata attestation)
external
view
returns (SpendAttestation memory spendAttestation);
/// Returns whether `token` is currently spendable on this deployment.
function isTokenSupported(address token) external view returns (bool);
/// Returns the current supported-token allowlist for this deployment.
function getSupportedTokens() external view returns (address[] memory);
/// Returns whether `spendSpecHash` has already been consumed on the destination-side contract.
function usedSpendSpecHashes(bytes32 spendSpecHash) external view returns (bool);
/// Returns the destination domain this deployment is configured for.
function domain() external view returns (uint32);
/// Returns the paired `TridentDeposits` contract used for same-chain settlement.
function tridentDeposits() external view returns (address);
/// Returns whether `signer` is currently authorized to sign spend attestations.
function isAttestationSigner(address signer) external view returns (bool);
/// Returns the keccak256 hash of the encoded attestation payload bytes.
function hashSpendAttestation(bytes calldata attestation) external pure returns (bytes32);
/// Returns the EIP-191 digest of the encoded attestation payload bytes.
function digestSpendAttestation(bytes calldata attestation) external pure returns (bytes32);
}
/// Minimal ERC-20 surface used by the SDK's deposit allowance flow.
#[sol(rpc)]
interface IERC20 {
/// Returns the remaining allowance `spender` can pull from `owner`.
function allowance(address owner, address spender) external view returns (uint256);
/// Sets `spender`'s allowance on the caller's balance to `value`.
function approve(address spender, uint256 value) external returns (bool);
}
}