# LND Postmortem By [Tiancheng Mai](https://x.com/TianchengMai) Last edited: 29 May 2025, 14:32 ``` // credit: TonyMa @mSKEvSgKg9U1fDm // thread: https://x.com/mSKEvSgKg9U1fDm/status/1921877267644350731 // author: // - https://archive.md/TJ6vo // archived threads: // - https://archive.md/3iiSm // - https://archive.md/qQjgk // - https://archive.md/OojEi // - https://archive.md/0ajQh // - https://archive.md/KwoFS ``` > Errata can be found in the comment section. > Updates are recorded in the comment section. Comments and suggestions are welcome :smile: ## Summary On May 9, 2025, LND (`LND.fi`) suffered a critical security breach resulting in the loss of approximately ~~$1.27 million~~ $1.42 million in user funds. The incident was triggered by a flawed contract deployment that intentionally expanded the privileges of the Pool Admin role. The deployer [0xc0454e29835479ee80d6f42965a16dcee9bfd868](https://sonicscan.org/address/0xc0454e29835479ee80d6f42965a16dcee9bfd868) of LND swept all assets. Specifically, the deployed `AToken` and `VariableDebtToken` contract modified the `onlyPool` access control modifier in `IncentivizedERC20.sol`, allowing the Pool Admin, held by the deployer address [0xc045...fd868](https://sonicscan.org/address/0xc0454e29835479ee80d6f42965a16dcee9bfd868), to invoke functions originally restricted to the Pool itself. Leveraging this, the deployer called `transferUnderlyingTo` on the `AToken` contract and drained all assets. ## Timeline - Mar-29-2025 09:51:06 PM UTC, the deployer became the Pool Admin role at [txn 0xd03b...a41a](https://sonicscan.org/tx/0xd03b7d80cf7fcd4d14076ca53d42bcfac0115674699adecb99dd3a769d5ea41a). - Mar-29-2025 09:52:23 PM UTC, the deployer initialized the modified `AToken` contract (`0xaa8cc9afe14f3a2b200ca25382e7c87cd883a527`) at [txn 0x2b24...e8d2](https://sonicscan.org/tx/0x2b246a7bcf34990765d66782111a1be3a8a21151e00d0c3cbc3c06c10eafe8d2). - Mar-29-2025 09:52:51 PM UTC, the deployer initialized the modified `VariableDebtToken` contract (`0x0b1a51c5cbffc636d79a072b8aa5a763cec42ef2`) at [txn 0x22a4...3fe5](https://sonicscan.org/tx/0x22a44525bc47c6a9ee95af7e2afc79fef7e8111ecf9879e411ba0c70890d3fe5). - May-09-2025 02:29:09 AM UTC, the deployer started draining all pools and deposited most funds to [0x5149...2cdd](https://sonicscan.org/address/0x5149a7696188f083297281d10293a20476252cdd) and [0x40c7...10c8](https://sonicscan.org/address/0x40c79ebc5a8ee251a9670ba3f4c5720f874410c8) via a series of `transferUnderlyingTo` invocations, starting from [txn 0xd52f...bffe](https://sonicscan.org/tx/0xd52f317b548bd0f67d32d35404d046e4e60f5af23dac8a502495a8714780bffe). - Most funds were transferred to [0x5149...2cdd](https://sonicscan.org/address/0x5149a7696188f083297281d10293a20476252cdd), [0x40c7...10c8](https://sonicscan.org/address/0x40c79ebc5a8ee251a9670ba3f4c5720f874410c8) and [0xc045...d868](https://sonicscan.org/address/0xc0454e29835479ee80d6f42965a16dcee9bfd868). - May-09-2025 02:39:22 AM UTC, [0x5149...2cdd](https://sonicscan.org/address/0x5149a7696188f083297281d10293a20476252cdd) started bridging the stolen funds via a series of txns, started from [txn 0xb287...8ee0](https://sonicscan.org/tx/0xb2875d27b3fda882ccb6a0f24d1d2da4093b76edf50f5cec47aa9cf1dcd98ee0). Most stolen funds were later bridged and are currently sitting in the following wallets: - (debridged again) ~~BSC [0x82be...14d9](https://bscscan.com/address/0x82be4fe84c2790023906c1648e0836ada67714d9)~~ - (debridged again) ~~BSC [0x8148...2f3e](https://bscscan.com/address/0x8148c4243f8cb49fe80d9e23df0bafc1c6732f3e)~~ - (debridged again) ~~BSC [0x5a94...1434](https://bscscan.com/address/0x5a94a3a114cf01f6a703dd8b840cf0a97cdf1434)~~ - (debridged again) ~~BSC [0x4b82...2fb1](https://bscscan.com/address/0x4b82e3485d33544561cd9a48410a605aa8892fb1)~~ - BSC [0x1405...1ab1](https://bscscan.com/address/0x140592a83052b3a432b6d70fb90764612ce41ab1): ~119k USD - BSC [0x9f6b...df5f](https://bscscan.com/address/0x9f6b0980d8a013cb17e028eb34360bfc1e3adf5f): ~313k USD - BSC [0x114d...c4b5](https://bscscan.com/address/0x114da8b1676d839abaac95da9083bbb497a1c4b5): ~354k USD - ETH [0xbd9e...c81f](https://etherscan.io/address/0xbd9e29232fead658f8b3c32b0869ab46cb5ac81f) (TradeOrge Deposit): ~397k USD - Transferred to TradeOrge Hot Wallet at [txn 0x9311...b462](https://etherscan.io/tx/0x931136dce8055f7cd54df4de73f969bd48694a541c82a09f0624bcb6cd9fb462). - HYPE [0x5149...2cdd](https://www.hyperscan.com/address/0x5149A7696188F083297281D10293a20476252CDD): ~240k USD (See [Stolen funds on Hyperliquid](#Stolen-funds-on-Hyperliquid)) - Transferred to MEXC Deposit Wallet at [txn 0x5f03...bd0a](https://www.hyperscan.com/tx/0x5f037d48dc97c6e94b3c33d7ebfcc0f8d49f371bf7b5bbbe37153c1916e9bd0a). Then, to MEXC hot wallet at [txn 0xd72f...0146](https://www.hyperscan.com/tx/0xd72f8e836ddb7f66ebb1b2db92b52d7d2291589a200b9070c714241511dc0146). - May-09-2025 09:19:36 AM UTC, the depolyer Pool Admin role was revoked by [0xe82e...aba4](https://sonicscan.org/address/0xe82e0ab25f8c4bd8ba9ff1216ef5a9f0b54aaba4) at [txn 0x74fa...b913](https://sonicscan.org/tx/0x74fadb3d2bdbcc215485537b69c8f25c2562981eee37c7014931941bdb39b913). ### Other related incidents: - May-01-2025 07:40:13 PM UTC, the deployer granted [0x9b64...b3f5](https://sonicscan.org/address/0x9b644a58713f5731be089620ec61bdb1075cb3f5) the Pool Admin role at [txn 0x14af...1560](https://sonicscan.org/tx/0x14af7939cd75045893621d6e1ca62a62f777c174a7b71fe1253eb3720f401560). - May-09-2025 02:35:41 AM UTC, the deployer granted [0x40c7...10c8](https://sonicscan.org/address/0x40c79ebc5a8ee251a9670ba3f4c5720f874410c8) the Pool Admin role at [txn 0x51ee...95e0](https://sonicscan.org/tx/0x51eef5c8bc981f5fa2f13a9fa4eb9ccdf56e39829e23b3a7c2379123bd4595e0). - May-09-2025 08:31:41 AM UTC, the deployer revoked [0x40c7...10c8](https://sonicscan.org/address/0x40c79ebc5a8ee251a9670ba3f4c5720f874410c8)'s the Pool Admin role at [txn 0x6d36...d25e8](https://sonicscan.org/tx/0x6d36421cdd5a97162567e9a6da25053aba68e7cc8cfb479c38b1bcf08afd25e8). - May-09-2025 09:16:47 AM UTC, the deployer granted [0xe82e...aba4](https://sonicscan.org/address/0xe82e0ab25f8c4bd8ba9ff1216ef5a9f0b54aaba4) the `0x00` role, which is the `DEFAULT_ADMIN_ROLE` at [txn 0x99fb...2a56](https://sonicscan.org/tx/0x99fb52c5e2d23dd3c2f2a9b5613b2ac4413e5775233bc2bcd6bcaa8db36a2a56). - May-09-2025 09:28:13 AM UTC, [0xe82e...aba4](https://sonicscan.org/address/0xe82e0ab25f8c4bd8ba9ff1216ef5a9f0b54aaba4) revoked the deployer's `0x00` role, which is the `DEFAULT_ADMIN_ROLE` at [txn 0xbd43...7d73](https://sonicscan.org/tx/0xbd43d950e856854621ca4a42e227c44f1a5a0459972a9969d723f2d577527d73). - May-09-2025 09:31:16 AM UTC, [0xe82e...aba4](https://sonicscan.org/address/0xe82e0ab25f8c4bd8ba9ff1216ef5a9f0b54aaba4) revoked [0x9b64...b3f5](https://sonicscan.org/address/0x9b644a58713f5731be089620ec61bdb1075cb3f5)'s the Pool Admin role at [txn 0x4cba...7a00](https://sonicscan.org/tx/0x4cba3e52ad97cae7455bd3d647e6add2a08822dd2c266e42744458c8d1227a00). ### Stolen funds on Hyperliquid - draining all Wrapped HYPE (WHYPE) tokens in the lending pool [0x6824...c759](https://www.hyperscan.com/address/0x6824429DDd4d3cE5Ff50e67e3CC909d7298dc759) via [txn 0x2609...9a37](https://www.hyperscan.com/tx/0x26095510aae7cec995b1e782be127a2db80899c6f8b845c04495a1dbb0349a37). - draining all Staked HYPE Shares (wstHYPE) and Staked HYPE (stHYPE) tokens in the lending pool [0x3383...a6C4](https://www.hyperscan.com/address/0x3383e37caD159bb00A56E330CE71d9F24e89a6C4) via [txn 0x5157...3a7f](https://www.hyperscan.com/tx/0x51571266f602b7e25e8ed1a144c05ed29756983d3f978277b4f5079b8e673a7f) - Hacker wallet on Hyperliquid: [0x5149...2CDD](https://www.hyperscan.com/address/0x5149A7696188F083297281D10293a20476252CDD) - MEXC deposit wallet: [0x24bc...eec5](https://www.hyperscan.com/address/0x24bc79bb8ef2fb1fd1da86f5b6de6140c720eec5) - MEXC hot wallet: [0x8D25...4608](https://www.hyperscan.com/address/0x8D25Fb438C6efCD08679ffA82766869B50E24608) On May 9th, the hacker sent all stolen tokens on Hyperliquid blockchain from Hacker wallet to MEXC deposit wallet via [txn 0x5f03...bd0a](https://www.hyperscan.com/tx/0x5f037d48dc97c6e94b3c33d7ebfcc0f8d49f371bf7b5bbbe37153c1916e9bd0a). Then, authorized and managed by MEXC, the MEXC deposit wallet sent 7380 HYPE tokens to MEXC hot wallet via [txn 0xd72f...0146](https://www.hyperscan.com/tx/0xd72f8e836ddb7f66ebb1b2db92b52d7d2291589a200b9070c714241511dc0146). ## 0x1: `onlyPool` access control modifier was compromised The deployer created a modified `AToken` contract (`0xaa8cc9afe14f3a2b200ca25382e7c87cd883a527`) where the `onlyPool` access control modifier was altered to allow not only the `Pool` contract but also any address with the Pool Admin role to invoke restricted functions. - The modified `AToken` contract: https://sonicscan.org/address/0xaa8cc9afe14f3a2b200ca25382e7c87cd883a527#code#F19#L47 -> `IncentivizedERC20.sol`. Note that the ` || aclManager.isPoolAdmin(msg.sender)` was added. ``` /** * @dev Only pool can call functions marked by this modifier. */ modifier onlyPool() { IACLManager aclManager = IACLManager( _addressesProvider.getACLManager() ); require( _msgSender() == address(POOL) || aclManager.isPoolAdmin(msg.sender), Errors.CALLER_MUST_BE_POOL ); _; } ``` - Original AAVE V3: https://github.com/aave-dao/aave-v3-origin/blob/464a0ea5147d204140ceda42a433656a58c8e212/src/contracts/protocol/tokenization/base/IncentivizedERC20.sol#L33-L39 ``` /** * @dev Only pool can call functions marked by this modifier. */ modifier onlyPool() { require(_msgSender() == address(POOL), Errors.CALLER_MUST_BE_POOL); _; } ``` ### `VariableDebtToken` contract is also modified - The modified `VariableDebtToken` contract: https://sonicscan.org/address/0x0b1a51c5cbffc636d79a072b8aa5a763cec42ef2#code#F20#L47 -> `IncentivizedERC20.sol`. Note that the ` || aclManager.isPoolAdmin(msg.sender)` was added. ``` /** * @dev Only pool can call functions marked by this modifier. */ modifier onlyPool() { IACLManager aclManager = IACLManager( _addressesProvider.getACLManager() ); require( _msgSender() == address(POOL) || aclManager.isPoolAdmin(msg.sender), Errors.CALLER_MUST_BE_POOL ); _; } ``` - Original AAVE V3: https://github.com/aave-dao/aave-v3-origin/blob/464a0ea5147d204140ceda42a433656a58c8e212/src/contracts/protocol/tokenization/base/IncentivizedERC20.sol#L33-L39 ### This modified contract was also deployed and tested on Sonic by a friend of the deployer https://sonicscan.org/find-similar-contracts?a=0x0b1a51c5cbffc636d79a072b8aa5a763cec42ef2&m=low&ps=25&mt=146 - The friend: [0xB8CaE283E7bFFE1F262d8276aBc79f85F9BEAC08](https://sonicscan.org/address/0xB8CaE283E7bFFE1F262d8276aBc79f85F9BEAC08). ## 0x2: The deployer held the Pool Admin role - list of related events: https://sonicscan.org/address/0x97f91ca15ce342ef92b6ca9673f5d5b44528bfa1#events - role granted txn: https://sonicscan.org/tx/0xd03b7d80cf7fcd4d14076ca53d42bcfac0115674699adecb99dd3a769d5ea41a - role revoked txn: https://sonicscan.org/tx/0x74fadb3d2bdbcc215485537b69c8f25c2562981eee37c7014931941bdb39b913 ## 0x3: The deployer called `transferUnderlyingTo` and swept all assets In original AAVE, only Pool can invoke `transferUnderlyingTo` and Pool Admin cannot. However, since `onlyPool` modifier was compromised, this is now possible. - `AToken.sol` contract addr: https://sonicscan.org/address/0xaa8cc9afe14f3a2b200ca25382e7c87cd883a527#code#F1#L156 ``` /// @inheritdoc IAToken function transferUnderlyingTo(address target, uint256 amount) external virtual override onlyPool { IERC20(_underlyingAsset).safeTransfer(target, amount); } ``` - this matches the original AAVE V3: https://github.com/aave-dao/aave-v3-origin/blob/464a0ea5147d204140ceda42a433656a58c8e212/src/contracts/protocol/tokenization/AToken.sol#L126-L129 ## Media Coverage Rekt: https://rekt.news/LNDFi-rekt DeFiHackLabs: https://defihacklabs.substack.com/p/lnd-postmortem-127-million-loss (Mandarin Chinese) @punkcan: https://x.com/punkcan/status/1923986038445212063 ## Disgrace Hall LND released [an official postmortem](https://medium.com/@lndfi/lnd-security-breach-post-mortem-2c54ac006050) (and [on X](https://x.com/Lnd_fi/status/1923003586859905319)), which just low-key plagiarized [@mSKEvSgKg9U1fDm](https://x.com/mSKEvSgKg9U1fDm) and this work without giving any credits... They took about a week to do a copy-paste and ChatGPT, I have no words... 😂 When [confronted](https://x.com/TianchengMai/status/1923017432546816411) by me, [LND replied](https://x.com/Lnd_fi/status/1923018719111909665) with this: > Your initial report had mistakes, you even had the deployer wallet incorrect, but you corrected it. Thank you for the report. OK. How convenient. LND, you are not welcome without credits. Thanks.