{"id":18542728,"url":"https://github.com/coinbase/magicspend","last_synced_at":"2025-04-06T03:07:03.102Z","repository":{"id":225174532,"uuid":"763829693","full_name":"coinbase/MagicSpend","owner":"coinbase","description":null,"archived":false,"fork":false,"pushed_at":"2024-11-25T23:38:56.000Z","size":341,"stargazers_count":95,"open_issues_count":0,"forks_count":16,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-03-30T02:05:48.051Z","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":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/coinbase.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":"audit/report-review-coinbase-magicspend.pdf","citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-02-27T01:47:46.000Z","updated_at":"2025-02-05T18:33:42.000Z","dependencies_parsed_at":"2024-03-22T22:27:46.580Z","dependency_job_id":"e9dac91b-fcd2-4c2f-ad03-6895ad08b6a5","html_url":"https://github.com/coinbase/MagicSpend","commit_stats":null,"previous_names":["coinbase/magic-spend","coinbase/magicspend"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coinbase%2FMagicSpend","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coinbase%2FMagicSpend/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coinbase%2FMagicSpend/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coinbase%2FMagicSpend/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/coinbase","download_url":"https://codeload.github.com/coinbase/MagicSpend/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247427006,"owners_count":20937201,"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-06T20:10:05.110Z","updated_at":"2025-04-06T03:07:03.084Z","avatar_url":"https://github.com/coinbase.png","language":"Solidity","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MagicSpend\n\nMagicSpend is a contract that allows onchain accounts to present valid Withdraw Requests and receive funds. A Withdraw Request is defined as\n\n```solidity\nstruct WithdrawRequest {\n    bytes signature;\n    address asset;\n    uint256 amount;\n    uint256 nonce;\n    uint48 expiry;\n }\n```\n\nWhere signature is an [EIP-191](https://eips.ethereum.org/EIPS/eip-191) compliant signature of the message\n\n```solidity\nabi.encode(\n  \u003cMagicSpend contract address\u003e,\n  \u003cUserOperation.sender and/or msg.sender of the withdraw call\u003e,\n  \u003cchain ID\u003e,\n  withdrawRequest.asset,\n  withdrawRequest.amount,\n  withdrawRequest.nonce,\n  withdrawRequest.expiry\n)\n```\n\nMagicSpend is an [ERC-4337](https://eips.ethereum.org/EIPS/eip-4337) compliant paymaster (EntryPoint [v0.6](https://github.com/eth-infinitism/account-abstraction/releases/tag/v0.6.0)) and also enables withdraw requests with asset ETH (`address(0)`) to be used to pay transaction gas.\n\nThis contract is part of a broader MagicSpend product from Coinbase, which as a whole allows Coinbase users to seamlessly use their assets onchain.\n\n\u003cimg width=\"661\" alt=\"Diagram of Coinbase user making use of MagicSpend\" src=\"https://github.com/coinbase/magic-spend/assets/6678357/42d3a8fc-a376-4139-9ea9-040cf094d74b\"\u003e\n\nWe have started a [discussion](https://ethereum-magicians.org/t/proposed-json-rpc-method-wallet-getassetbalance/) around a possible new wallet RPC to enable apps to have better awareness of this \"just in time\" funding.\n\n## Detailed Flows\n\nWhen the withdrawing account is an ERC-4337 compliant smart contract (like [Smart Wallet](https://github.com/coinbase/smart-wallet)), there are three different ways the MagicSpend smart contract can be used\n\n1. Pay gas only\n2. Transfer funds during execution only\n3. Pay gas and transfer funds during execution\n\n### Pay gas only\n\n\u003cimg width=\"901\" alt=\"Pay gas only flow diagram\" src=\"https://github.com/coinbase/magic-spend/assets/6678357/21274fb0-b901-4e20-bc1c-f320caa76e5b\"\u003e\n\n1. A ERC-4337 UserOperation is submitted to the bundler. The paymasterAndData field includes the MagicSpend address and the withdrawal request.\n2. Bundler (EOA) calls EntryPoint smart contract.\n3. Entrypoint first calls to `UserOperation.sender`, a smart contract wallet (SCW), to validate the user operation.\n4. Entrypoint decrements the paymaster’s deposit in the Entrypoint. If the paymaster’s deposit is less than the gas cost, the transaction will revert.\n5. EntryPoint calls the MagicSpend contract to run validations on the withdrawal, including checking the signature and ensuring withdraw.value is greater than transaction max gas cost.\n6. Entrypoint calls to SCW with `UserOperation.calldata`\n7. SCW does arbitrary operation, invoked by `UserOperation.calldata`.\n8. Entrypoint makes post-op call to MagicSpend, with actual gas used in transaction.\n9. MagicSpend sends the SCW any withdraw.value minus actual gas used.\n10. Entrypoint refunds the paymaster if actual gas \u003c estimated gas from (4.)\n11. Entrypoint pays bundler for tx gas\n\n### Transfer funds during execution only\n\n\u003cimg width=\"600\" alt=\"Diagram of 'Transfer funds during execution only' flow\" src=\"https://github.com/coinbase/magic-spend/assets/6678357/124548ca-209d-41ac-844a-cbf5717a702e\"\u003e\n\nThis is the simplest flow. The MagicSpend account is agnostic to any details of this transaction, even whether or not the caller is a SCW. It simply validates the withdraw and transfers funds if valid.\n\n### Pay gas and transfer funds during execution\n\n\u003cimg width=\"898\" alt=\"Pay gas and transfer funds during execution\" src=\"https://github.com/coinbase/magic-spend/assets/6678357/4b81fea7-9b45-4cfd-acdb-66f88f6bc642\"\u003e\n\nThis flow is like \"Pay gas only” with the addition of (7.) and (8.). Here, the SCW also requests funds during execution. In this flow, a user might be, for example, trying to mint an NFT and needs funds for the mint.\n\n## Deployments\n\n| Network      | Contract Address                                                                                                              |\n| ------------ | ----------------------------------------------------------------------------------------------------------------------------- |\n| Base         | [0x011A61C07DbF256A68256B1cB51A5e246730aB92](https://basescan.org/address/0x011A61C07DbF256A68256B1cB51A5e246730aB92)         |\n| Base Sepolia | [0x011A61C07DbF256A68256B1cB51A5e246730aB92](https://sepolia.basescan.org/address/0x011a61c07dbf256a68256b1cb51a5e246730ab92) |\n\n## Developing\n\nAfter cloning the repo, run the tests using Forge, from [Foundry](https://github.com/foundry-rs/foundry?tab=readme-ov-file)\n\n```bash\nforge test\n```\n\nYou can run the echinda tests with this make command\n\n```bash\nmake echidna-test\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoinbase%2Fmagicspend","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcoinbase%2Fmagicspend","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoinbase%2Fmagicspend/lists"}