Sitowise
Payouts

Destination addresses

A withdrawal can be sent anywhere. The address that owns the node sends the transaction; where the ETH lands is a separate argument, typed into the call at the moment you make it.

Two addresses, two jobs

AddressRoleChecked how
Node ownerAuthorises the withdrawal by sending the transactionnode.owner == msg.sender, in the contract
DestinationReceives the ETHNot checked against anything. It is the to argument you pass.
SitowiseFactory
function withdraw(uint256 id, address to) external;
function withdrawAll(address to) external returns (uint256 amount);

Nothing binds the destination in advance, and nothing needs to. The only authority the contract recognises is msg.sender, so a withdrawal sent by anyone other than the node owner reverts with NotNodeOwner before the destination matters at all. Since you are the one making the call, you are also the one naming the recipient, and there is no step in between where it could be swapped.

Why you might use it

  • Buying from a hot wallet and sweeping payouts to a cold one, without ever moving the node.
  • Sending to an exchange deposit address, where supported by that exchange.
  • Paying out to a shared address for a group that funded the node.

Since a node cannot be transferred, this is the only way to change where value ends up without buying a new node. See Node model.

Rules the contract enforces

  • The destination cannot be the zero address. Passing it reverts with BadInput.
  • The destination must be able to receive ETH. Value is sent with a plain call, so a contract without a payable receive or fallback reverts the whole withdrawal with TransferFailed.
  • The contract always sends the node’s whole balance. There is no amount argument, so the destination receives all of it or the transaction reverts and none of it moves.
  • In withdrawAll, every node the wallet owns pays into the same destination. One call, one recipient, one transfer carrying the combined total. To split across addresses, make separate withdraw calls.
  • The destination has no bearing on ownership. Sending a payout somewhere does not give that address any claim on the node, and the node keeps accruing to the same owner.

Sending to a contract

A contract can receive a withdrawal if it accepts plain ETH transfers. Three things to keep in mind:

  • The transfer forwards all remaining gas rather than a fixed stipend, so a receiver doing real work will not run out for that reason alone. It will still revert the whole withdrawal if its own logic reverts.
  • The contract is reentrancy guarded and the balance is zeroed before the transfer, so a receiver that calls back into withdraw gains nothing and gets Reentrancy for trying.
  • Some multisigs and custody contracts refuse plain transfers, and there is no way to tell from the address alone. If you are not certain, withdraw one node with a small balance first and confirm it arrived before sweeping the rest.

Confirming where it went

Every payout emits an event naming the destination, so the record is on chain and does not depend on this site.

The event
event Withdrawn(uint256 indexed id, address indexed to, uint256 amount);

Both the node id and the destination are indexed, so you can filter by either. withdrawAll emits one Withdrawn per node it emptied, every one of them naming the same destination, which is how a sweep stays readable per node afterwards. Reading events is described on Events, and the same history is available over HTTP from GET /api/node/:id.