diff --git a/docs/cow-protocol/reference/contracts/core/README.mdx b/docs/cow-protocol/reference/contracts/core/README.mdx index c3eadbfd9..bedd68418 100644 --- a/docs/cow-protocol/reference/contracts/core/README.mdx +++ b/docs/cow-protocol/reference/contracts/core/README.mdx @@ -75,6 +75,22 @@ If developing smart contracts that create orders, make sure at a contract level ::: +### Signed fee amount + +The order struct still contains a `feeAmount` field, which the settlement contract honors: if an order is signed with a non-zero `feeAmount`, that amount is transferred from the user in addition to the executed sell amount (pro rata for partially fillable orders). +The limit price is checked against `sellAmount` and `buyAmount` only, so the effective price of an order with a signed fee is `buyAmount / (sellAmount + feeAmount)`. + +The protocol no longer uses signed fees. Fees are included in the order's limit price, and the API rejects any order with a non-zero `feeAmount` (`NonZeroFee` error). On-chain orders (e.g. ETH flow) with a non-zero fee are recorded with a placement error and excluded from auctions. + +Charging the signed `feeAmount` once per order, and the resulting effective price, is expected behavior: the user explicitly signed both. +This doesn't apply to orders with zero amounts, which can be executed more than once and charge the fee repeatedly (see [Orders with zero amounts](#orders-with-zero-amounts)). + +:::tip + +Always sign orders with `feeAmount = 0`. + +::: + ### `ERC-1271` Replayability The security of [`ERC-1271`](../core/signing-schemes#erc-1271) signatures depend on the developers' implementation of the _signing smart contract_. diff --git a/docs/cow-protocol/reference/contracts/core/settlement.md b/docs/cow-protocol/reference/contracts/core/settlement.md index ea26fe818..07755abbf 100644 --- a/docs/cow-protocol/reference/contracts/core/settlement.md +++ b/docs/cow-protocol/reference/contracts/core/settlement.md @@ -97,7 +97,7 @@ struct Data { | `buyAmount` | Amount of `buyToken` that is bought in wei | | `validTo` | UNIX timestamp (in seconds) until which the order is valid | | `appData` | Extra information about the order. Not enforced by the smart contract outside of signature verification (may be used for referrals etc). | -| `feeAmount` | Amount of fees paid in `sellToken` wei | +| `feeAmount` | Amount of fees paid in `sellToken` wei. Must be `0`: the API rejects orders with a non-zero `feeAmount` (see [Signed fee amount](/cow-protocol/reference/contracts/core#signed-fee-amount)) | | `kind` | `buy` or `sell` | | `partiallyFillable` | partially fillable (`true`) or fill-or-kill (`false`) | | `sellTokenBalance` | From where the `sellToken` balance is withdrawn | diff --git a/docs/cow-protocol/reference/core/auctions/schema.md b/docs/cow-protocol/reference/core/auctions/schema.md index 1e9ddafab..26cde9589 100644 --- a/docs/cow-protocol/reference/core/auctions/schema.md +++ b/docs/cow-protocol/reference/core/auctions/schema.md @@ -99,7 +99,7 @@ This key maps to a list containing the set of orders in the batch. Each entry in - `quote`: the winning quote for that order. - `penaltyCapNative`: a stringified integer denoting the cap on the penalty a solver can incur for winning this order but not settling it within the auction deadline, measured in terms of the smallest denomination of the native token of the chain. See the [solver rewards](/cow-protocol/reference/core/auctions/rewards#penalty-caps) page for how this cap is computed and used. - We clarify here that all `market` orders have a potentially non-zero predetermined fee, while all `limit` orders have necessarily a zero signed fee, and the actual fee charged to the order is computed and provided by the solvers when they propose an execution of such an order. More details are provided in the [solutions section](#solutions-output). + We clarify here that all orders have a zero signed fee (`feeAmount`), and the actual fee charged to the order is computed and provided by the solvers when they propose an execution of such an order. More details are provided in the [solutions section](#solutions-output). An example Fill-or-Kill user limit buy order that sells 1000 [COW](https://etherscan.io/token/0xdef1ca1fb7fbcdc777520aa7f396b4e015f497ab) for at least 284.138335 USDC [USDC](https://etherscan.io/token/0xba100000625a3754423978a60c9317c58a424e3d) is given below: diff --git a/docs/cow-protocol/reference/core/intents/README.mdx b/docs/cow-protocol/reference/core/intents/README.mdx index 6030d23d4..9125cc3aa 100644 --- a/docs/cow-protocol/reference/core/intents/README.mdx +++ b/docs/cow-protocol/reference/core/intents/README.mdx @@ -16,7 +16,7 @@ The parameters required for an intent can be broken down into three categories: * amounts to swap (i.e. `sellAmount` and `buyAmount`) * kind of swap (i.e. `sell` or `buy`) * partial fillability (i.e. `true` or `false`) -* fees payable to the protocol (i.e. `feeAmount`) +* signed fee (i.e. `feeAmount`), which must be `0`: fees are included in the limit price instead ### Co-ordination / Settlement