2

Is there some way to call sp.address inside an entrypoint and pass in a dynamic String?

I have created an example contract showing the failing state:

import smartpy as sp

class DynamicAddressTestContract(sp.Contract):
    def __init__(self, **kargs):
        self.init(**kargs)

    @sp.entry_point
    def test(self, params):
        sp.set_type(params.address, sp.TString)
        addr = sp.address(params.address)
        sp.verify(addr == sp.sender, "INVALID_ADDRESS")
    
@sp.add_test(name = "Dynamic Address")
def test():
    scenario = sp.test_scenario()
    scenario.h1("Unpacked")
    c1 = DynamicAddressTestContract()
    scenario += c1
    alice = sp.test_account("alice")
    
    c1.test(address='tz1h4EsGunH2Ue1T2uNs8mfKZ8XZoQji3HcK').run(sender=alice)

The error is:

Error: Cannot convert expression to bool. Conditionals are forbidden on
contract expressions. Please use ~ or sp.if instead of not or if.

 SmartPy code line 18, in test (line 18)
   scenario += c1
 SmartPy code line 10, in test (line 10)
   addr = sp.address(params.address)

Why does this fail?

Is there a way to fix this or perhaps another way to achieve this objective?

Link to Contract on SmartPy

1 Answer 1

2

That is not possible, sp.address(x) expects x to be a python string.

params.address is a michelson value of type string and michelson does not have any instruction to explicitly cast a string to an address. But you could probably do some "black magic" with sp.pack, sp.slice and sp.unpack to extract the address from a string.

The proper way to do it is to change params.address to be of type address and to remove sp.address(...).

import smartpy as sp

class DynamicAddressTestContract(sp.Contract):
    def __init__(self, **kargs):
        self.init(**kargs)

    @sp.entry_point
    def test(self, params):
        sp.set_type(params.address, sp.TAddress)
        sp.verify(params.address == sp.sender, "INVALID_ADDRESS")
    
@sp.add_test(name = "Dynamic Address")
def test():
    scenario = sp.test_scenario()
    scenario.h1("Unpacked")
    c1 = DynamicAddressTestContract()
    scenario += c1
    alice = sp.test_account("alice")
    
    c1.test(address=sp.address('tz1h4EsGunH2Ue1T2uNs8mfKZ8XZoQji3HcK')).run(sender=alice)
3
  • i see, thank you for the clear explanation. i'm essentially looking for any way to compare a string version of an address with an actual address, via any intermediary type. as far as i can see the closest is to go from raw address > pack+slice to bytes -> encode to base256 > encode to base58 > pack+slice > comparable string but i am still figuring out the base256 and base58 part. there must be an easier way
    – 0x10
    May 18 at 7:38
  • Too much trouble (byte manipulation is not great in Michelson). Also, you do not really need it. May 18 at 8:05
  • while in 99% of cases i would agree with you there are always outliers, and in this case i really and truly do need to achieve this objective in order for the current problem i'm working to be considered solved, so i think i will skip base256 and try to use a straight up base58 byte to character map
    – 0x10
    May 18 at 8:11

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.