Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

In Solidity, a push payment sends funds to a recipient during the operation that creates or distributes the payment. A pull payment records what the recipient is owed and lets a later withdrawal transaction collect it. Pull payments usually isolate the initiating operation from untrusted recipient code, but they do not remove the need for checks-effects-interactions, reentrancy defenses, failure handling, or correct accounting.

What the two payment patterns mean

The distinction is about when value is delivered and which transaction is responsible for invoking the recipient.

Push payments

A push design transfers Ether as part of the function that creates a reward, processes a sale, distributes fees, or pays several recipients. The initiating transaction both changes the contract’s accounting and calls each recipient. A simplified form looks like this:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
function pay(address payable recipient, uint256 amount) external {
    require(credit[recipient] >= amount, "insufficient credit");

    (bool sent, ) = recipient.call{value: amount}("");
    require(sent, "payment failed");

    credit[recipient] -= amount;
}

The example is deliberately problematic: it performs an external call before reducing the recorded credit. If recipient is a contract, that call transfers control to code chosen by the recipient. The recipient can execute a fallback or receive function, call back into the paying contract, and observe the old balance before the subtraction occurs.

#1 Best Overall
Ledger Nano X - Classic Crypto Wallet with Bluetooth | Compact, go anywhere, 1.1" display. Desktop & iOS/Android compatible
  • Effortlessly build your crypto portfolio via the all in one Ledger Wallet app: buy, sell, send, receive, swap, stake and more across popular blockchains. 15,000+ coins & tokens in a single dashboard. Keep a close eye on the market. Compare service providers. Track performance. Get timely alerts. Build your portfolio with confidence.
  • Enjoy Bluetooth connectivity, iOS access, and hours of battery use with this mobile-first, secure backup signer. Freedom you can depend on.
  • Genuine Check: confirm your signer is authentic during setup with the Ledger Wallet app.
  • Protect your signer: keep it in mint condition at all times with a bespoke Pod or Case to avoid scratches and everyday wear and tear.

Pull payments (the withdrawal pattern)

A pull design splits the work into two transactions. The first records an obligation; the second is a withdrawal initiated for that obligation.

mapping(address => uint256) private pending;

function recordPayment(address payee, uint256 amount) internal {
    pending[payee] += amount;
}

function withdrawPayments() external {
    uint256 amount = pending[msg.sender];
    require(amount > 0, "nothing to withdraw");

    pending[msg.sender] = 0;

    (bool sent, ) = payable(msg.sender).call{value: amount}("");
    require(sent, "withdrawal failed");
}

This is the withdrawal pattern shown in the Solidity documentation: checks are performed first, the pending amount is cleared, and only then does the contract interact with the recipient. Ethereum.org describes the same model as requiring users to withdraw funds from the contract themselves.

Why a direct payment call exposes recipient behavior

An address is not necessarily a passive wallet. When a contract calls another contract, execution can enter the callee’s code. That code can consume gas, revert, emit effects, make further calls, or attempt to call back into the original contract. Solidity’s security guidance treats reentrancy as a consequence of calls to other contracts generally, not merely as an Ether-transfer issue.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Reentrancy caused by stale state

Suppose a contract stores a recipient’s credit and sends the money before decrementing that credit. A malicious recipient can reenter a withdrawal function while the credit still contains the original amount. If the function can be called repeatedly before the first invocation finishes, the same credit may be used more than once. The vulnerable ordering is:

  1. Read the amount owed.
  2. Call the recipient.
  3. Update the amount owed.

The safer ordering is:

  1. Validate authorization and the amount owed.
  2. Set the owed amount to zero or subtract the amount being withdrawn.
  3. Call the recipient and check whether the call succeeded.

Clearing the state before the call means a reentrant invocation sees no remaining balance for that withdrawal. If the external call reverts and the whole transaction reverts, the state change is rolled back atomically, allowing a later retry. If a design intentionally catches a failed call instead of reverting, it must explicitly decide whether and how to restore the obligation; silently deleting it would lose the payee’s funds.

Rank #2
Sale
TANGEM Crypto Wallet Pack of 3 – Trusted Cold Storage Hardware Wallet | 100% offline; Bitcoin, Ethereum, NFTs & altcoins; No seed phrase; NFC; Pack of 3, Self custody wallet
  • Seedless by design, nothing to steal: Your private key is generated inside the EAL6+ chip and never leaves it. No seed phrase is shown or typed at setup, so a tampered device, keylogger, or phishing site has nothing to capture. 9+ years, millions of cards, no known remote hacks.
  • Tap once to manage your entire crypto wallet across 90 blockchains - no USB cables or Bluetooth, no batteries, no setup. Access 16,100+ coins & tokens, DeFi, NFTs, and staking instantly from your phone
  • Backup without a seed phrase: Your wallet is copied to 2 backup cards with end-to-end encryption, so there are no words on paper to lose or leak. Keep them in separate places; if one card is lost, the others restore full access. Optional seed phrase for advanced users.
  • Engineered to last up to 25 years: Waterproof (IP69K), shockproof and tested for extreme temperatures from −25°C to 50°C. A durable cold wallet with long‑term protection and independently audited security.
  • Trusted by 6 million users worldwide (4.9 App Store, 4.8 Google Play) - buy, sell, swap, stake, and spend cryptocurrency directly. The secure offline storage wallet designed for how people actually use crypto wallets

Recipient rejection and failure propagation

A synchronous push makes the recipient’s behavior part of the sender’s transaction. A recipient contract can reject the call, run out of gas, or otherwise return failure. If the payer uses a reverting check, the operation that created the payment also fails. In a distribution loop, one incompatible recipient can prevent later recipients from being paid or force the entire batch to revert, depending on the loop’s error handling.

Pull payments move that interaction to a withdrawal transaction. Recording a liability does not require the recipient to accept Ether immediately, so a recipient that cannot receive funds synchronously does not necessarily block the sale, auction, reward calculation, or other operation that created the liability. The withdrawal can be retried or handled separately according to the contract’s policy.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How pull payments isolate the initiating operation

Isolation is the principal reason to prefer a pull design when payees are untrusted or may be incompatible. The operation that establishes an entitlement performs accounting only: it increases pending[payee] (or deposits the amount into an escrow). No recipient code runs in that transaction. The later withdrawal is a separate interaction whose caller, gas cost, and failure are visible to the party collecting the money.

This separation changes what can fail:

Decision axis Push payment Pull payment
Recipient code during the initiating operation Yes; the payer calls the recipient as part of the operation. No; the initiating operation records an obligation. Recipient code runs only during withdrawal.
State-ordering risk Payment logic must update balances before each external call; an incorrect order can permit reentrancy. The withdrawal function still needs checks-effects-interactions and safe accounting before its external call.
Failure propagation A rejected or reverting recipient can revert or block the operation that is distributing funds. The original operation can complete while a failed withdrawal remains a separate collection problem.
User experience The payer’s transaction attempts delivery immediately. The payee needs a later withdrawal transaction; the payee or an authorized third party must initiate it.
Gas responsibility The initiating transaction pays for delivery to all recipients it processes. The withdrawal transaction consumes gas; the account submitting it pays unless the system provides a relayer or other arrangement.
Accounting Flow can look simpler, but delivery and business-state updates are tightly coupled. Requires pending-payment bookkeeping, withdrawal authorization, and a policy for failed withdrawals.
Batch behavior One recipient can affect other recipients when they share a transaction. Each payee can withdraw independently, so one payee’s behavior does not normally block another’s withdrawal.

Implementing a secure withdrawal function

Use the following sequence when designing or reviewing a pull-payment contract.

1. Define exactly what creates a debt

Choose the event that makes a payment due: a completed sale, a finalized auction, a reward calculation, or another state transition. Increase the payee’s pending amount in that same state transition. Use addition rather than replacement when a payee can earn multiple payments before withdrawing. The contract must also ensure that the total recorded liabilities are backed by Ether or by whatever asset is promised.

Rank #3
TANGEM Crypto Wallet Pack of 2 – Trusted Cold Storage Hardware Wallet | 100% offline; Bitcoin, Ethereum, NFTs & altcoins; No seed phrase; NFC, Self custody wallet
  • Seedless by design, nothing to steal: Your private key is generated inside the EAL6+ chip and never leaves it. No seed phrase is shown or typed at setup, so a tampered device, keylogger, or phishing site has nothing to capture. 9+ years, millions of card.
  • Tap once to manage your entire crypto wallet across 90 blockchains - no USB cables or Bluetooth, no batteries, no setup. Access 16,100+ coins & tokens, DeFi, NFTs, and staking instantly from your phone
  • Backup without a seed phrase: Your wallet is copied to 2 backup cards with end-to-end encryption, so there are no words on paper to lose or leak. Keep them in separate places; if one card is lost, the others restore full access. Optional seed phrase for advanced users.
  • Engineered to last up to 25 years: Waterproof (IP69K), shockproof and tested for extreme temperatures from −25°C to 50°C. A durable cold wallet with long‑term protection and independently audited security.
  • Trusted by 6 million users worldwide - buy, sell, swap, stake, and spend cryptocurrency directly. The secure offline storage wallet designed for how people actually use crypto wallets

2. Restrict who may create or change credit

Only the intended business operation should increase a payee’s balance. Do not expose a general-purpose function that lets arbitrary callers credit themselves unless that is explicitly part of the protocol. Check roles, ownership, signatures, or the state of the underlying transaction before recording a payment.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

3. Read and validate the pending amount

The withdrawal function should identify the payee and require a nonzero amount. If the API lets someone withdraw for another account, make that behavior explicit: the beneficiary is the account receiving the funds, while the transaction sender may be a different account.

4. Apply effects before interaction

Set the pending amount to zero, or reduce it by the amount being withdrawn, before making the external call. This is the effects portion of Solidity’s checks-effects-interactions pattern. If partial withdrawals are supported, subtract the exact amount and preserve any remainder before the call.

5. Make the external call and verify its result

Use the transfer mechanism appropriate to the contract and check the returned success value. A failed call should follow a deliberate policy: reverting preserves the pending balance through transaction rollback, while a non-reverting design must retain the debt and expose a way to retry or redirect it. Never mark a payment as delivered merely because an external call was attempted.

6. Protect against reentrancy and cross-function interactions

Clearing one mapping entry before a call prevents a common repeated-withdrawal bug, but it is not a complete audit. Check whether the recipient can reenter another function that observes related state, whether multiple assets share accounting, and whether a callback can reach administrative or settlement logic. A reentrancy guard can add defense in depth where the contract’s invariants warrant it. Solidity’s security documentation emphasizes that reentrancy can arise from calls to other contracts generally, so review token transfers, hooks, callbacks, and arbitrary interfaces as well as Ether sends.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #4
DCENT Hardware Wallet | Biometric Cold Storage, Bluetooth, Multi-Crypto
  • EAL5+ CERTIFIED SECURE ELEMENT + FINGERPRINT PROTECTION — Your private keys stay encrypted offline on a certified EAL5+ chip, the same security tier used in EMV bank cards. Built by DCENT, securing crypto since 2018. Fingerprint authentication adds a second layer no PIN-only wallet can match.
  • 10,000+ ASSETS NATIVE ON 100+ BLOCKCHAINS — Hold Bitcoin, Ethereum, XRP, Solana, Cardano, popular stablecoins (USDT, USDC), and NFTs in one wallet. No third-party apps, no fragmented setup — every supported asset works straight out of the box.
  • TAP-TO-SIGN MOBILE EXPERIENCE — Pair your wallet with the DCENT mobile app over Bluetooth. Manage tokens, review transactions, and access in-app swap features directly from your phone — no cables, no desktop required.
  • WEB3 & dAPP ACCESS VIA METAMASK — Connect to MetaMask and other browser extension wallets to manage NFTs, claim airdrops, and access dApps. A large screen and intuitive 4-button interface keep every transaction clearly visible before you sign.
  • SEAMLESS FIRMWARE UPDATES & 30-DAY MONEY-BACK GUARANTEE — Apply security updates without resetting your wallet or migrating funds. Backed by Amazon's 30-day money-back guarantee — your purchase is risk-free.

Using an escrow implementation

OpenZeppelin’s PullPayment implementation, documented in its Contracts 3.x API reference, keeps funds in an intermediate Escrow contract. A payer records a payment for a payee, and the payee later retrieves it through withdrawPayments. The documentation states that any account can call the withdrawal function for a payee. That can help a protocol whose intended recipient cannot or will not submit a transaction: another account can submit the transaction while the funds still go to the payee.

That convenience does not make the recipient call harmless. The documented implementation forwards all gas to the recipient, which means recipient code has room to execute and potentially reenter. The same guidance recommends trusting the recipient or applying checks-effects-interactions and/or a reentrancy guard. Treat the API details as version-specific: the cited payment page is for Contracts 3.x, while another cited OpenZeppelin page is explicitly for version 4.x and older. Confirm the API and security notes for the exact library version pinned by a project rather than copying an example unchanged.

Why the old “transfer is safe” shortcut is inadequate

Older Solidity advice often presented transfer as intrinsically safe because it supplied a fixed gas stipend to the recipient. Current Solidity documentation instead recommends the withdrawal pattern for funds sent as the result of an effect, and current security guidance focuses on state ordering and reentrancy across external calls. Gas assumptions and recipient code can change as the ecosystem evolves; a fixed stipend is not a substitute for correct invariants, failure handling, and review.

This does not mean every push payment is exploitable or that every use of call is wrong. A push can be reasonable when the recipient is controlled or trusted, the call is deliberately isolated, state is updated first, failure behavior is acceptable, and the contract has been tested against the relevant callbacks. The point is to avoid treating a transfer primitive as a security policy.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

When a push payment can still be appropriate

  • Known recipient set: The contract pays accounts whose code and behavior are controlled by the system, or the protocol explicitly accepts their ability to reject payment.
  • Small, isolated interaction: The payment is not embedded in a loop or a state transition where a failed recipient would strand unrelated work.
  • Correct state ordering: All balances and one-time claims are updated before the external interaction.
  • Explicit failure policy: The design specifies whether a failed payment reverts the operation, records a retryable debt, or routes funds elsewhere.
  • Tested callbacks: Tests cover reverting recipients, gas-consuming recipients, reentrant recipients, and recipients that call other public functions.

If any of these assumptions are uncertain, recording a debt and letting the payee withdraw is generally the more isolating design.

Best Value
Trezor Safe 7 Crypto Hardware Wallet with Bluetooth for Android/iOS/Desktop | Charcoal Black, Aluminum Unibody, 2,5" TouchScreen, Wireless Charging, Quantum-Ready, IP54, Long-Lasting LiFePO? Battery
  • Dual-chip architecture for maximum protection: The next-gen, fully auditable TROPIC01 chip works alongside a certified EAL6+ Secure Element—completely NDA-free—to deliver radically transparent, industry-leading defense against physical attacks.
  • Quantum-ready security: Get protection against future threats with the first-ever hardware wallet designed with quantum-ready architecture.
  • See every detail with confidence: Our largest high-resolution color touchscreen makes it easy to navigate your assets, review transactions and manage your coins with clarity.
  • Wireless freedom with encrypted Bluetooth control: Manage, buy, swap and stake securely using Trezor Suite on desktop or mobile. Qi2-compatible wireless charging keeps your Trezor powered up. No cables required—security meets convenience.
  • Works seamlessly with Android, iOS and desktop: Connect wirelessly or via USB-C to your phone or computer. Manage your crypto anywhere with our companion Trezor Suite app.

Pull-payment trade-offs developers must plan for

The payee must perform another transaction

Pull payments add a user action. A wallet user may need to click a withdrawal button, wait for a relayer, or use a script. The withdrawal consumes gas, and someone must pay that gas. If the payee is a contract that cannot initiate transactions, the protocol should document whether any account may call withdrawal for that payee and ensure the beneficiary address cannot be changed by the caller.

Pending balances become protocol state

Every payment creates a liability that must be represented, queried, and reconciled. Decide how the contract handles many small credits, zero-value entries, emergency recovery, upgrades, and migrations. If payments are denominated in several tokens, keep separate accounting for each asset and ensure a withdrawal for one asset cannot consume another asset’s balance.

Withdrawal availability is still a security property

A pull system is not complete if withdrawals can be permanently blocked by an owner-only switch, a pause condition with no recovery path, an incorrect recipient check, or an unbounded loop. Keep withdrawal logic bounded and independently callable. If the system supports pausing, define whether already-recorded liabilities remain withdrawable and how they are released after an incident.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Testing and review checklist

  • Verify that every payment-creating path increases the correct payee’s pending balance exactly once.
  • Verify that withdrawing twice without a new credit cannot receive the same amount twice.
  • Use a malicious recipient contract that reenters the withdrawal function and other public functions.
  • Use a recipient that deliberately reverts, consumes substantial gas, or has no payable receive function.
  • Check that a failed withdrawal preserves the obligation when the chosen policy is retryable.
  • Check that one payee’s failure cannot prevent unrelated payees from recording or withdrawing their funds.
  • Test withdrawals submitted by an account other than the beneficiary when the interface allows that behavior.
  • Reconcile the contract’s Ether balance with the sum of pending liabilities and any deliberately reserved funds.
  • Review token callbacks and external hooks using the same reentrancy analysis as Ether calls.
  • Pin and review the exact Solidity compiler and payment-library versions used by the deployment.

How the pattern fits security standards

The OWASP Smart Contract Security Verification Standard 0.0.1, dated 2024-10-04, includes a business-logic requirement that the withdrawal process use a pull-based approach to track accounting and allow users to pull payments. This is a stated control in that standard, not a legal requirement or proof that every contract must use pull payments. It is useful as a review checkpoint alongside threat modeling and tests tailored to the protocol.

A practical decision rule

Ask whether the operation that creates the payment should be allowed to execute arbitrary recipient code. If the answer is no, record the obligation and use a withdrawal pattern. If the answer is yes, document why the recipient is trusted or why failure is acceptable, update state before the call, check the result, and test reentrancy across the entire contract rather than only the payment function.

Pull payments reduce the blast radius of recipient behavior: a recipient’s rejection normally affects its own withdrawal instead of the transaction that created everyone else’s entitlement. They do not eliminate external calls, gas costs, bookkeeping, or cross-function invariants. The withdrawal function remains security-critical and must be implemented and reviewed as such.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.