{"id":19096821,"url":"https://github.com/makerdao/dss-flash","last_synced_at":"2025-04-18T16:31:15.356Z","repository":{"id":40349632,"uuid":"290598958","full_name":"makerdao/dss-flash","owner":"makerdao","description":"MakerDAO Flash Mint Module","archived":true,"fork":false,"pushed_at":"2023-03-07T16:17:24.000Z","size":97,"stargazers_count":49,"open_issues_count":4,"forks_count":37,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-03-11T19:49:47.613Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Solidity","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/makerdao.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-08-26T20:34:41.000Z","updated_at":"2024-12-05T17:35:23.000Z","dependencies_parsed_at":"2024-11-09T03:37:58.348Z","dependency_job_id":"0e294f2c-a1e7-4e2b-9886-e2a4dffd9a98","html_url":"https://github.com/makerdao/dss-flash","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/makerdao%2Fdss-flash","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/makerdao%2Fdss-flash/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/makerdao%2Fdss-flash/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/makerdao%2Fdss-flash/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/makerdao","download_url":"https://codeload.github.com/makerdao/dss-flash/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249517936,"owners_count":21284861,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-09T03:37:54.298Z","updated_at":"2025-04-18T16:31:15.110Z","avatar_url":"https://github.com/makerdao.png","language":"Solidity","readme":"# dss-flash\n![Build Status](https://github.com/makerdao/dss-flash/actions/workflows/.github/workflows/tests.yaml/badge.svg?branch=master)\n\nFlash Mint Module for the Maker protocol - an implementation of [MIP25](https://forum.makerdao.com/t/mip25-flash-mint-module/4400). This module conforms to the [ERC3156 spec](https://eips.ethereum.org/EIPS/eip-3156) so please read this over to get a firm idea of the considerations/risks.\n\n## Usage\n\nSince this module conforms to the ERC3156 spec, you can just use the reference borrower implementation from the spec:\n\n```\npragma solidity ^0.8.0;\n\nimport \"./interfaces/IERC20.sol\";\nimport \"./interfaces/IERC3156FlashBorrower.sol\";\nimport \"./interfaces/IERC3156FlashLender.sol\";\n\ncontract FlashBorrower is IERC3156FlashBorrower {\n    enum Action {NORMAL, OTHER}\n\n    IERC3156FlashLender lender;\n\n    constructor (\n        IERC3156FlashLender lender_\n    ) public {\n        lender = lender_;\n    }\n\n    /// @dev ERC-3156 Flash loan callback\n    function onFlashLoan(\n        address initiator,\n        address token,\n        uint256 amount,\n        uint256 fee,\n        bytes calldata data\n    ) external override returns (bytes32) {\n        require(\n            msg.sender == address(lender),\n            \"FlashBorrower: Untrusted lender\"\n        );\n        require(\n            initiator == address(this),\n            \"FlashBorrower: Untrusted loan initiator\"\n        );\n        (Action action) = abi.decode(data, (Action));\n        if (action == Action.NORMAL) {\n            require(IERC20(token).balanceOf(address(this)) \u003e= amount);\n            // make a profitable trade here\n            IERC20(token).transfer(initiator, amount + fee);\n        } else if (action == Action.OTHER) {\n            // do another\n        }\n        return keccak256(\"ERC3156FlashBorrower.onFlashLoan\");\n    }\n\n    /// @dev Initiate a flash loan\n    function flashBorrow(\n        address token,\n        uint256 amount\n    ) public {\n        bytes memory data = abi.encode(Action.NORMAL);\n        uint256 _allowance = IERC20(token).allowance(address(this), address(lender));\n        uint256 _fee = lender.flashFee(token, amount);\n        uint256 _repayment = amount + _fee;\n        IERC20(token).approve(address(lender), _allowance + _repayment);\n        lender.flashLoan(this, token, amount, data);\n    }\n}\n```\n\n## Vat Dai\n\nIt may be that users are interested in moving dai around in the internal vat balances. Instead of wasting gas by minting/burning ERC20 dai you can instead use the vat dai flash mint function to short cut this.\n\nThe vat dai version of flash mint is roughly the same as the ERC20 dai version with a few caveats:\n\n### Function Signature\n\n`vatDaiFlashLoan(IVatDaiFlashBorrower receiver, uint256 amount, bytes calldata data)`\n\nvs\n\n`flashLoan(IERC3156FlashBorrower receiver, address token, uint256 amount, bytes calldata data)`\n\nNotice that no token is required because it is assumed to be vat dai. Also, the `amount` is in RADs and not in WADs.\n\n### Approval Mechanism\n\nERC3156 specifies using a token approval to approve the amount to repay to the lender. Unfortunately vat dai does not have a way to specify delegation amounts, so instead of giving the flash mint module full rights to withdraw any amount of vat dai we have instead opted to have the receiver push the balance owed at the end of the transaction.\n\n### Example\n\nHere is an example similar to the one above to showcase the differences:\n\n```\npragma solidity ^0.6.12;\n\nimport \"dss-interfaces/dss/VatAbstract.sol\";\n\nimport \"./interfaces/IERC3156FlashLender.sol\";\nimport \"./interfaces/IVatDaiFlashBorrower.sol\";\n\ncontract FlashBorrower is IVatDaiFlashBorrower {\n    enum Action {NORMAL, OTHER}\n\n    VatAbstract vat;\n    IVatDaiFlashLender lender;\n\n    constructor (\n        VatAbstract vat_,\n        IVatDaiFlashLender lender_\n    ) public {\n        vat = vat_;\n        lender = lender_;\n    }\n\n    /// @dev Vat Dai Flash loan callback\n    function onVatDaiFlashLoan(\n        address initiator,\n        uint256 amount,\n        uint256 fee,\n        bytes calldata data\n    ) external override returns (bytes32) {\n        require(\n            msg.sender == address(lender),\n            \"FlashBorrower: Untrusted lender\"\n        );\n        require(\n            initiator == address(this),\n            \"FlashBorrower: Untrusted loan initiator\"\n        );\n        (Action action) = abi.decode(data, (Action));\n        if (action == Action.NORMAL) {\n            // do one thing\n        } else if (action == Action.OTHER) {\n            // do another\n        }\n\n        // Repay the loan amount + fee\n        // Be sure not to overpay as there are no safety guards for this\n        vat.move(address(this), lender, amount + fee);\n\n        return keccak256(\"VatDaiFlashBorrower.onVatDaiFlashLoan\");\n    }\n\n    /// @dev Initiate a flash loan\n    function vatDaiFlashBorrow(\n        uint256 amount\n    ) public {\n        bytes memory data = abi.encode(Action.NORMAL);\n        lender.vatDaiFlashLoan(this, amount, data);\n    }\n}\n\n```\n\n## Deployment\n\nTo deploy this contract run the following commands:\n\n`make deploy-mainnet` for mainnet deployment\n\n`make deploy-goerli` for goerli deployment\n\nDeployed Goerli address: [0xAa5F7d5b29Fa366BB04F6E4c39ACF569d5214075](https://goerli.etherscan.io/address/0xAa5F7d5b29Fa366BB04F6E4c39ACF569d5214075#code)  \nDeployed Mainnet address: [0x60744434d6339a6B27d73d9Eda62b6F66a0a04FA](https://etherscan.io/address/0x60744434d6339a6B27d73d9Eda62b6F66a0a04FA#code)  \n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmakerdao%2Fdss-flash","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmakerdao%2Fdss-flash","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmakerdao%2Fdss-flash/lists"}