Skip to content

Instantly share code, notes, and snippets.

@andywer
Last active June 19, 2023 09:21
Show Gist options
  • Save andywer/edad1b4fb84d2770433cf22e094bc1fd to your computer and use it in GitHub Desktop.
Save andywer/edad1b4fb84d2770433cf22e094bc1fd to your computer and use it in GitHub Desktop.
Draft: Delegating AML to DeFi pools

Draft: AML Delegation to DeFi Pools

There is a looming risk in DeFi concerning real-world assets (RWAs) or security tokens in general and pools holding them (think Uniswap, AAVE, …) regarding Anti Money Laundering (AML) regulation.

Should a court order the token issuer (i.e. Circle) to freeze the holdings of an address that has deposited the funds into a pool (i.e. UniV3-ETH/USDC), that might risk the token issuer having to freeze the whole pool's holdings.

This risk is even amplified in the new Uniswap v4 architecture as all pools' funds will be held by a single contract, rather than each pool holding its own funds separately.

Proposed Solution

In order to mitigate that risk, pools could implement a protocol that allows the regulated token issuers to delegate their AML actions to these pools, so they can be enforced on a per-liquidity-provider basis.

So in case of our hypothetical court order, the pool would freeze the sanctioned address' LP token and potentially even transfer their share of the pooled principle back to the token issuer.

While that approach ideologically goes somewhat against the original intention behind crypto currencies, it just makes sense to manage risks and comply with legislation in a densly regulated space like RWAs.

Details

Freezing

Each regulated token needs to provide a set of functions for delegating their AML actions. It could be implemented by a contract that's separate from the token contract, but it would need to be discoverable via the token contract's address (details tbd).

interface UpstreamAML {
    function isFrozen(address holder) external view returns (bool);
}

The pool on the other hand needs to check on every LP token interaction (deposit, withdrawal, transfer) if the holder is sanctioned by any of the principle tokens.

Seizing

interface UpstreamAML {
    struct SeizureWarrant {
        address holder;
        uint256 amount;
        bool    seizeAll;
    }
    
    event Seizure(
        uint256 indexed warrantID,
        address indexed holder,
        uint256 amount
    );

    function getSeizureWarrant(uint256 id) external view returns (SeizureWarrant);
    function hasBeenSeized(uint256 id, address fromPool) external view returns (bool);

    /** Seizes funds from the caller. */
    function seize(uint256 warrantID, uint256 amount) external;
}

The pool would need to implement an additional interface.

interface DownstreamAML {
    interface Seizure {
        address holder;
        address token;
        uint256 warrantID;
        uint256 amount;
    }

    /** Permissionless. Anyone can call the function, but will only do anything if there is an upstream warrant. */
    function seizeHoldings(address holder) external returns (Seizure[] calldata);
}

Open Questions

  • Clarify exact requirements
  • Are seizures necessary or is it sufficient to freeze the LP tokens?
  • How to discover upstream AML contract (if not part of token contract)?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment