2

In this answer, the answerer suggested that CREATE_CONTRACT could be used to generate a contract address which could then be used as a seed for a pseudorandom number in a contract.

What would a simple example of this look like when using Smartpy?

For context, my end goal would be to provide an endpoint that receives payment, generates a pseudo-random number (via the above method) and then mints an NFT with attributes based partially on the random result.

4

For the example provided by Rafael, you can do the following in SmartPy.

import smartpy as sp

class Creator(sp.Contract):
    def __init__(self):
        self.init(address = sp.none)
        
    @sp.entry_point
    def generate_address(self):
        # Generate the address but don't append the operation
        contract = sp.create_contract_operation(sp.Contract(), sp.unit, sp.tez(0), None);
        self.data.address = sp.some(sp.pack(contract.address))
        
@sp.add_test(name = "generate_address")
def test():
    scenario = sp.test_scenario()
    c1 = Creator()
    scenario += c1
    c1.generate_address()

this.storage.address will contain the "random" value.

Something similar to: 0x050a0000001601294ce4766fe8c9a9aa375b5413de86998127ffd100

2
1

Heres how I ended up doing it. NOTE: this is not at all truly random do not use this for any purposes other than a very very weak random number generator with no funds associated with the output

def get_random(self):
    ha = sp.bytes("0x")
    bytes_to_nat = sp.local('bytes_to_nat',{})
    bytes_to_nat.value = {
            sp.bytes('0x00'): 0, sp.bytes('0x01'): 1,
            sp.bytes('0x02'): 2, sp.bytes('0x03'): 3,
            sp.bytes('0x04'): 4, sp.bytes('0x05'): 5,
            sp.bytes('0x06'): 6, sp.bytes('0x07'): 7,
            sp.bytes('0x08'): 8, sp.bytes('0x09'): 9,
            sp.bytes('0x0a'): 10, sp.bytes('0x0b'): 11,
            sp.bytes('0x0c'): 12, sp.bytes('0x0d'): 13,
            sp.bytes('0x0e'): 14, sp.bytes('0x0f'): 15,
            sp.bytes('0x10'): 16, sp.bytes('0x11'): 17,
            sp.bytes('0x12'): 18, sp.bytes('0x13'): 19,
            sp.bytes('0x14'): 20, sp.bytes('0x15'): 21,
            sp.bytes('0x16'): 22, sp.bytes('0x17'): 23,
            sp.bytes('0x18'): 24, sp.bytes('0x19'): 25,
            sp.bytes('0x1a'): 26, sp.bytes('0x1b'): 27,
            sp.bytes('0x1c'): 28, sp.bytes('0x1d'): 29,
            sp.bytes('0x1e'): 30, sp.bytes('0x1f'): 31,
            sp.bytes('0x20'): 32, sp.bytes('0x21'): 33,
            sp.bytes('0x22'): 34, sp.bytes('0x23'): 35,
            sp.bytes('0x24'): 36, sp.bytes('0x25'): 37,
            sp.bytes('0x26'): 38, sp.bytes('0x27'): 39,
            sp.bytes('0x28'): 40, sp.bytes('0x29'): 41,
            sp.bytes('0x2a'): 42, sp.bytes('0x2b'): 43,
            sp.bytes('0x2c'): 44, sp.bytes('0x2d'): 45,
            sp.bytes('0x2e'): 46, sp.bytes('0x2f'): 47,
            sp.bytes('0x30'): 48, sp.bytes('0x31'): 49,
            sp.bytes('0x32'): 50, sp.bytes('0x33'): 51,
            sp.bytes('0x34'): 52, sp.bytes('0x35'): 53,
            sp.bytes('0x36'): 54, sp.bytes('0x37'): 55,
            sp.bytes('0x38'): 56, sp.bytes('0x39'): 57,
            sp.bytes('0x3a'): 58, sp.bytes('0x3b'): 59,
            sp.bytes('0x3c'): 60, sp.bytes('0x3d'): 61,
            sp.bytes('0x3e'): 62, sp.bytes('0x3f'): 63,
            sp.bytes('0x40'): 64, sp.bytes('0x41'): 65,
            sp.bytes('0x42'): 66, sp.bytes('0x43'): 67,
            sp.bytes('0x44'): 68, sp.bytes('0x45'): 69,
            sp.bytes('0x46'): 70, sp.bytes('0x47'): 71,
            sp.bytes('0x48'): 72, sp.bytes('0x49'): 73,
            sp.bytes('0x4a'): 74, sp.bytes('0x4b'): 75,
            sp.bytes('0x4c'): 76, sp.bytes('0x4d'): 77,
            sp.bytes('0x4e'): 78, sp.bytes('0x4f'): 79,
            sp.bytes('0x50'): 80, sp.bytes('0x51'): 81,
            sp.bytes('0x52'): 82, sp.bytes('0x53'): 83,
            sp.bytes('0x54'): 84, sp.bytes('0x55'): 85,
            sp.bytes('0x56'): 86, sp.bytes('0x57'): 87,
            sp.bytes('0x58'): 88, sp.bytes('0x59'): 89,
            sp.bytes('0x5a'): 90, sp.bytes('0x5b'): 91,
            sp.bytes('0x5c'): 92, sp.bytes('0x5d'): 93,
            sp.bytes('0x5e'): 94, sp.bytes('0x5f'): 95,
            sp.bytes('0x60'): 96, sp.bytes('0x61'): 97,
            sp.bytes('0x62'): 98, sp.bytes('0x63'): 99,
            sp.bytes('0x64'): 100, sp.bytes('0x65'): 101,
            sp.bytes('0x66'): 102, sp.bytes('0x67'): 103,
            sp.bytes('0x68'): 104, sp.bytes('0x69'): 105,
            sp.bytes('0x6a'): 106, sp.bytes('0x6b'): 107,
            sp.bytes('0x6c'): 108, sp.bytes('0x6d'): 109,
            sp.bytes('0x6e'): 110, sp.bytes('0x6f'): 111,
            sp.bytes('0x70'): 112, sp.bytes('0x71'): 113,
            sp.bytes('0x72'): 114, sp.bytes('0x73'): 115,
            sp.bytes('0x74'): 116, sp.bytes('0x75'): 117,
            sp.bytes('0x76'): 118, sp.bytes('0x77'): 119,
            sp.bytes('0x78'): 120, sp.bytes('0x79'): 121,
            sp.bytes('0x7a'): 122, sp.bytes('0x7b'): 123,
            sp.bytes('0x7c'): 124, sp.bytes('0x7d'): 125,
            sp.bytes('0x7e'): 126, sp.bytes('0x7f'): 127,
            sp.bytes('0x80'): 128, sp.bytes('0x81'): 129,
            sp.bytes('0x82'): 130, sp.bytes('0x83'): 131,
            sp.bytes('0x84'): 132, sp.bytes('0x85'): 133,
            sp.bytes('0x86'): 134, sp.bytes('0x87'): 135,
            sp.bytes('0x88'): 136, sp.bytes('0x89'): 137,
            sp.bytes('0x8a'): 138, sp.bytes('0x8b'): 139,
            sp.bytes('0x8c'): 140, sp.bytes('0x8d'): 141,
            sp.bytes('0x8e'): 142, sp.bytes('0x8f'): 143,
            sp.bytes('0x90'): 144, sp.bytes('0x91'): 145,
            sp.bytes('0x92'): 146, sp.bytes('0x93'): 147,
            sp.bytes('0x94'): 148, sp.bytes('0x95'): 149,
            sp.bytes('0x96'): 150, sp.bytes('0x97'): 151,
            sp.bytes('0x98'): 152, sp.bytes('0x99'): 153,
            sp.bytes('0x9a'): 154, sp.bytes('0x9b'): 155,
            sp.bytes('0x9c'): 156, sp.bytes('0x9d'): 157,
            sp.bytes('0x9e'): 158, sp.bytes('0x9f'): 159,
            sp.bytes('0xa0'): 160, sp.bytes('0xa1'): 161,
            sp.bytes('0xa2'): 162, sp.bytes('0xa3'): 163,
            sp.bytes('0xa4'): 164, sp.bytes('0xa5'): 165,
            sp.bytes('0xa6'): 166, sp.bytes('0xa7'): 167,
            sp.bytes('0xa8'): 168, sp.bytes('0xa9'): 169,
            sp.bytes('0xaa'): 170, sp.bytes('0xab'): 171,
            sp.bytes('0xac'): 172, sp.bytes('0xad'): 173,
            sp.bytes('0xae'): 174, sp.bytes('0xaf'): 175,
            sp.bytes('0xb0'): 176, sp.bytes('0xb1'): 177,
            sp.bytes('0xb2'): 178, sp.bytes('0xb3'): 179,
            sp.bytes('0xb4'): 180, sp.bytes('0xb5'): 181,
            sp.bytes('0xb6'): 182, sp.bytes('0xb7'): 183,
            sp.bytes('0xb8'): 184, sp.bytes('0xb9'): 185,
            sp.bytes('0xba'): 186, sp.bytes('0xbb'): 187,
            sp.bytes('0xbc'): 188, sp.bytes('0xbd'): 189,
            sp.bytes('0xbe'): 190, sp.bytes('0xbf'): 191,
            sp.bytes('0xc0'): 192, sp.bytes('0xc1'): 193,
            sp.bytes('0xc2'): 194, sp.bytes('0xc3'): 195,
            sp.bytes('0xc4'): 196, sp.bytes('0xc5'): 197,
            sp.bytes('0xc6'): 198, sp.bytes('0xc7'): 199,
            sp.bytes('0xc8'): 200, sp.bytes('0xc9'): 201,
            sp.bytes('0xca'): 202, sp.bytes('0xcb'): 203,
            sp.bytes('0xcc'): 204, sp.bytes('0xcd'): 205,
            sp.bytes('0xce'): 206, sp.bytes('0xcf'): 207,
            sp.bytes('0xd0'): 208, sp.bytes('0xd1'): 209,
            sp.bytes('0xd2'): 210, sp.bytes('0xd3'): 211,
            sp.bytes('0xd4'): 212, sp.bytes('0xd5'): 213,
            sp.bytes('0xd6'): 214, sp.bytes('0xd7'): 215,
            sp.bytes('0xd8'): 216, sp.bytes('0xd9'): 217,
            sp.bytes('0xda'): 218, sp.bytes('0xdb'): 219,
            sp.bytes('0xdc'): 220, sp.bytes('0xdd'): 221,
            sp.bytes('0xde'): 222, sp.bytes('0xdf'): 223,
            sp.bytes('0xe0'): 224, sp.bytes('0xe1'): 225,
            sp.bytes('0xe2'): 226, sp.bytes('0xe3'): 227,
            sp.bytes('0xe4'): 228, sp.bytes('0xe5'): 229,
            sp.bytes('0xe6'): 230, sp.bytes('0xe7'): 231,
            sp.bytes('0xe8'): 232, sp.bytes('0xe9'): 233,
            sp.bytes('0xea'): 234, sp.bytes('0xeb'): 235,
            sp.bytes('0xec'): 236, sp.bytes('0xed'): 237,
            sp.bytes('0xee'): 238, sp.bytes('0xef'): 239,
            sp.bytes('0xf0'): 240, sp.bytes('0xf1'): 241,
            sp.bytes('0xf2'): 242, sp.bytes('0xf3'): 243,
            sp.bytes('0xf4'): 244, sp.bytes('0xf5'): 245,
            sp.bytes('0xf6'): 246, sp.bytes('0xf7'): 247,
            sp.bytes('0xf8'): 248, sp.bytes('0xf9'): 249,
            sp.bytes('0xfa'): 250, sp.bytes('0xfb'): 251,
            sp.bytes('0xfc'): 252, sp.bytes('0xfd'): 253,
            sp.bytes('0xfe'): 254, sp.bytes('0xff'): 255
        }
    nat_value = 0
    contract = sp.create_contract_operation(sp.Contract(), sp.unit, sp.tez(0), None);        
    # Convert given string (as bytes) to sha256 hash
    b = sp.pack(contract.address)
    ha = sp.sha256(b)
    # Iterate over each byte of the hash and look up the corresponding int value from our big table above
    x = sp.local('x', 0)
    # Store the 'total' Nat value of the bytes
    total = sp.local('total', 0)
    hash_len = sp.local("hash_len", sp.len(ha))
    sp.while x.value < hash_len.value:
        # Add to previous total and then multiple the new value by 256
        total.value = (total.value + bytes_to_nat.value.get(sp.slice(ha, x.value, 1).open_some())) * 256
        sp.if total.value >= 1000000000000000:
            x.value = 1000000000000000
        sp.else:
            x.value = x.value + 1
    num = (total.value // 10)
    return num
1
  • I'd be interested in hearing how the create_contract call generates the hash returned and how deterministic it is. Bonus points for explaining how easy/hard it would be to exploit it.
    – Geoff
    13 hours ago

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.