# mev-boost with unconditional payment
The original mev-boost design achieves security by introducing a trusted relay which receives payloads from builders, validates them, creates a proof of it's value, and submits it to validators.
This has the following security concerns ([discussed here](https://hackmd.io/@flashbots/r1CuVl86Y)):
1. relay reports inaccurate value
2. relay submits invalid payload
3. relay withholds the payload body
4. relay steals the builder's block
In this document, we explore an mev-boost design which uses unconditional payments to mitigate these concerns.
## architecture
In this construction, a trusted payment escrow would replace a trusted relay.
This escrow would work in the following manner:
- the builder deposits ETH into a contract owned by the escrow daemon
- the builder can request to exit the account using a timelock
- to publish a payload, the builder sends the payload header along with a signed payment permission to the escrow daemon
- the escrow daemon validates the payment permission and publishes the payload header to the validator
- the validator returns the `SignedBlindedBeaconBlock` to all escrows (preferably, by publishing it to a p2p channel)
- upon receiving this signed block, the escrow generates and submits the payment transaction to the network using the signed permission of the associated builder
- the escrow forwards the `SignedBlindedBeaconBlock` to the builder for them to insert the transaction list and publish to the network
## key considerations
- Builders must keep open a balance with every escrow they send payloads to and have it funded with sufficient eth to cover the value of the block they are proposing. Builders without access to up front capital could use a third party to validate and front the necessary eth.
- Escrows never take custody of the funds as the eth can only be transferred to an address specified by the builder.
- Escrows could propose a block and never send a payment to the validators. A validator needs to be able to identify an escrow missbehaving in this manner and disconnect from receiving further payloads.
- Escrows could censor or deprioritize a block builder by not forwarding their payload requests to validators.
- Escrows could execute a payment even if a validator did not include the payload in a block.
- Escrows could perform censorship attacks against eachother to prevent payments from settling within the expiry period.
## example escrow contract
```solidity
contract Escrow {
event Payment(address builder, address feeRecipient, uint256 amount, uint256 nonce, uint256 expiry, bytes32 blockhash);
struct Account {
uint256 timelock;
uint256 balance;
uint256 nonce;
}
mapping[address => Account] accounts;
address immutable admin;
uint256 immutable timelockDuration;
constructor(address a, uint256 t) {
admin = a;
timelockDuration = t;
}
// builder deposits eth into their account
receive() public payable {
accounts[msg.sender].balance += msg.value;
}
// escrow executes payment
function pay(address feeRecipient, uint256 amount, uint256 nonce, uint256 expiry, bytes32 blockhash, bytes memory permission) public {
require(msg.sender == admin);
require(block.number <= expiry);
bytes memory msg = keccak256(abi.encodePacked(feeRecipient, amount, nonce, expiry, blockhash));
address builder = ecrecover(msg, permission);
require(nonce >= accounts[builder].nonce);
accounts[builder].nonce = nonce + 1;
accounts[builder].balance -= amount;
payable(feeRecipient).transfer(amount);
emit Payment(builder, feeRecipient, amount, nonce, expiry, blockhash);
}
// builder requests exit
function requestExit() public {
require(accounts[msg.sender].timelock == 0);
accounts[msg.sender].timelock = block.number + timelockDuration;
}
// builder confirms exit
function confirmExit() public {
Account memory account = accounts[msg.sender];
require(account.timelock != 0 && block.number >= account.timelock);
delete accounts[msg.sender];
payable(msg.sender).transfer(account.balance);
}
}
```