1

In an auction-like setup, I'd like to be able to automatically "refund" players if they get outbid.

It seems like everyone recommends a manual "safe withdraw" pattern, where the player would have to trigger the withdraw function on the Auction contract in order to be refunded, but this seems like terrible UX. Is there any way around this without compromising security?

0

From what I understand, when a user bids, he sends ether (or tokens), so they're on the contract. So the withdrawal doesn't have to be triggered by them.

One thing you could do is to let the outbidder trigger the refund. Consider the following scenario:

  • user 1 makes a first bidding. He sends ether to the contract.

  • user 2 makes a higher bidding, sending more ether than user 1. The bid function does the same thing as for user 1, except it also triggers the refund to user 1.

It's a pretty naive solution, but I don't think there are any security issues with doing that.

3
  • Thanks for the answer, this is ideally what I'd like to do (and what I'd originally done), but from my understanding, if my bid function triggers the refund, then since contracts can be set up to execute functions when they receive payment, someone could set up a malicious contract that executes a failing function whenever it receives payment, and so if they receive a refund from the auction, the whole of the auction's bid function ends up failing. Have I misunderstood?
    – Taimur
    May 15 '18 at 10:33
  • @Taimur What do you mean "contracts can be set up to execute functions when they receive payment"? What contracts exactly? And "malicious contracts", don't you have one auction contract? May 15 '18 at 12:16
  • 3
    @TeleportingGoat he means if a contract bid on the auction, and was then outbid, the refund of ether to them would execute the fallback function on the outbid contract. this could then fail and fail the entire bid. The way around this is to use send instead of transfer, which works the same but returns a boolean true for success and false for failure instead of throwing like transfer.
    – natewelch_
    May 15 '18 at 12:25
0

There's a way to force a transfer, example of forceful transfer by jbaylina.

The main idea is that a contract that selfdestructs can transfer its full balance without triggering the fallback function of the target.

In the linked example a small contract is deployed that is similar to

contract SafeSend {
    constructor(address payable recipient) public payable {
        selfdestruct(recipient);
    }
}

Since you are skipping the fallback function it is possible that the recipient contract is not aware of such funds.

1
  • I think this is not what OP is asking about. Mar 24 '19 at 16:32
0

In your particular case it is possible, because refund of previous highest bidder could be triggered by the new highest bidder like this:

function bid () public payable {
    if (msg.value > highestBid) {
        if (highestBid > 0 && !highestBidder.send (highestBid))
            refundBalances [highestBidder] += highestBid;

        highestBidder = msg.sender;
        highestBid = msg.value;
    }
}

Note, that bid function does not throw on failed refund, but rather increases refund balance. Otherwise malicious bidder would be able to prevent outbids by rejecting refunds. So separate withdraw function will still be needed to trigger refund in case automatic refund failed for some reason.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.