{{ message }}

Instantly share code, notes, and snippets.

# SamWilsn/DSA.md Secret

Last active Jan 24, 2020

### Arbitrary State Access

Arbitrary state access is a read or write to a storage slot specified by another storage slot.

#### Example

This example is a loose approximation of an auction contract. Each new highest bidder locks in Ether as their bid, and the previous bidder is refunded.

``````refund_addr: address
refund_amount: wei_value

@public
@payable
assert msg.value > self.refund_amount

self.refund_amount = msg.value
``````

#### Explanation

To show how this is DSA, imagine a scenario given the two following transactions {and their witnesses}:

• `bid('0xB', 4)` {`refund_addr == 0xA && refund_amount == 3 && (0xA).balance == 2`}
• `bid('0xC', 5)` {`refund_addr == 0xA && refund_amount == 3 && (0xA).balance == 2`}

If `bid('0xB', 4)` is included in the block first, the witnesses included by `bid('0xC', 5)` will be missing the state at `0xB`.

### Branched State Access

A branched state access is a read or write to a storage slot selected from a list known ahead of time.

#### Example

``````troz: int128
poit: int128
narf: int128

@public
if self.troz < 5:
self.troz = self.poit + value
else:
self.troz = self.narf + value
``````

#### Explanation

To show how this is DSA, imagine a scenario given the two following transactions {and their witnesses}:

• `add_value(2)` { `troz == 3 && poit == 5` }
• `add_value(3)` { `troz == 3 && poit == 5` }

If `add_value(2)` is included in the block first, the witnesses included by `add_value(3)` will be missing the state for `narf`.

Unlike Arbitrary State Access, it is possible to create a witness that is guaranteed to be sufficient by unconditionally adding `poit` and `narf`:

• `add_value(2)` { `troz == 3 && poit == 5 && narf == 11` }
• `add_value(3)` { `troz == 3 && poit == 5 && narf == 11` }

### Predicted State Access

#### Example

``````previous_addr: address

@public
@payable
def dweep():
``````

While `dweep` contains DSA, a transaction cannot be invalidated by a preceding transaction in the same block.

Regardless of whether `dweep()[value=11,sender=0xB]` is included before `dweep()[value=23,sender=0xC]` or vise versa, every state access will have a value (provided by the preceding transaction.)

Explanation

Consider these transactions {and their witnesses}:

• `dweep()[value=11,sender=0xB]` { `previous_addr = 0xA && (0xB).balance = 13` }
• `dweep()[value=23,sender=0xC]` { `previous_addr = 0xA && (0xC).balance = 29` }

If `dweep()[value=11,sender=0xB]` is included first, the state accesses for `dweep()[value=23,sender=0xC]` look like:

• `(0xC).balance == 29` is included in `dweep()[value=23,sender=0xC]`'s witness.
• `previous_addr == 0xB` is known after `dweep()[value=11,sender=0xB]` is executed.
• `(0xB).balance == 2` is known after `dweep()[value=11,sender=0xB]` is executed.

On the other hand, if `dweep(23)` is included first, the state accesses for `dweep(11)` look like:

• `(0xB).balance == 13` is included in `dweep()[value=11,sender=0xB]`'s witness.
• `previous_addr == 0xC` is known after `dweep()[value=23,sender=0xC]` is executed.
• `(0xC).balance == 6` is known after `dweep()[value=23,sender=0xC]` is executed.