Usurpation of Identity

The previous section used the liquidity contract admins.liq and its techelson version admins.tz. It showcased how to handle expected transfer failures and turn them into test objectives. The failure used to demonstrate the example was that we tried to add a new administrator by calling the contract from the testcase, which failed because only administrators can add other administrators, and the (address of the) testcase was not registered as such.

    PUSH @amount mutez 0 ;

    # New admin's address.
    DUUUUP ;
    # New admin's name.
    PUSH @new_name string "new_admin" ;
    PAIR ;
    # Root's name.
    PUSH @name string "root" ;
    PAIR @storage ;

    TRANSFER_TOKENS ;
    PUSH (option string) (Some "illegal access to admin account") ;
    MUST_FAIL @this_must_fail string ;
    PRINT_STACK ;

    DIP {NIL operation } ;
    CONS ;
    APPLY_OPERATIONS ;

One solution would be to register the testcase directly, but it would be more natural and more generic to be able to apply a transfer as someone else. Hence the SET_SOURCE extension:

instruction parameter stack
SET_SOURCE code :: address : 'A
-> 'B
iff code :: [ A -> B ]

Warning: the SET_SOURCE extension is only legal in testcases.

This extension allows to pretend the testcase is a live contract or account from the environment. More precisely, all operations created in the code under the SET_SOURCE will have their source and sender be the address from the stack. Testcase setSource.techel uses this instruction to pretend that root is the one adding a new administrator.

    # New admin's address.
    DUUUUP ;
    # New admin's name.
    PUSH @new_name string "new_admin" ;
    PAIR ;
    # Root's name.
    PUSH @name string "root" ;
    PAIR @storage ;

    {   # Pretending to be `root`.
        DUUUUUUP ;
        PRINT_STACK ;
        STEP ;
        SET_SOURCE {
            TRANSFER_TOKENS
        }
    } ;

    PRINT_STACK ;

    DIP { NIL operation } ;
    CONS ;

    APPLY_OPERATIONS

The testcase now succeeds, and its output is

$ techelson --contract rsc/admins/contracts/admins.tz -- rsc/admins/okay/setSource.techel
Running test `SetSource`

running test script...
   timestamp: 1970-01-01 00:00:00 +00:00

applying operation CREATE[uid:2] (@address[3]@admins, "sha512:@contract_manager", None, false, true, 0utz) "Admins"
   timestamp: 1970-01-01 00:00:00 +00:00
   live contracts: none
=> live contracts: <anonymous> (0utz) address[2]@new_admin
                   Admins (0utz) address[3]@admins
                   <anonymous> (0utz) address[1]@root

running test script...
   timestamp: 1970-01-01 00:00:00 +00:00
stack:
|==================================================================================================|
|                                                                                            @root |
| address[1]@root                                                                                  |
| address                                                                                          |
|--------------------------------------------------------------------------------------------------|
|                                                                                       @new_admin |
| address[2]@new_admin                                                                             |
| address                                                                                          |
|--------------------------------------------------------------------------------------------------|
| address[3]@admins                                                                                |
| (contract (pair string (pair string address)))                                                   |
|--------------------------------------------------------------------------------------------------|
| address[3]@admins                                                                                |
| (contract (pair string (pair string address)))                                                   |
|--------------------------------------------------------------------------------------------------|
|                                                                                          @amount |
| 0utz                                                                                             |
| mutez                                                                                            |
|--------------------------------------------------------------------------------------------------|
|                                                                                         @storage |
| ("root", ("new_admin", address[2]@new_admin))                                                    |
| (pair string (pair string address))                                                              |
|--------------------------------------------------------------------------------------------------|
| address[1]@root                                                                                  |
| address                                                                                          |
|==================================================================================================|

running test script...
   timestamp: 1970-01-01 00:00:00 +00:00
stopping [no information] press `return` to continue


running test script...
   timestamp: 1970-01-01 00:00:00 +00:00
stack:
|==================================================================================================|
|                                                                                            @root |
| address[1]@root                                                                                  |
| address                                                                                          |
|--------------------------------------------------------------------------------------------------|
|                                                                                       @new_admin |
| address[2]@new_admin                                                                             |
| address                                                                                          |
|--------------------------------------------------------------------------------------------------|
| address[3]@admins                                                                                |
| (contract (pair string (pair string address)))                                                   |
|--------------------------------------------------------------------------------------------------|
| TRANSFER[uid:3] address[1]@root -> address[3]@admins 0utz ("root", ("new_admin", address[2]@new_admin)) |
| operation                                                                                        |
|==================================================================================================|

running test script...
   timestamp: 1970-01-01 00:00:00 +00:00

applying operation TRANSFER[uid:3] address[1]@root -> address[3]@admins 0utz ("root", ("new_admin", address[2]@new_admin))
   timestamp: 1970-01-01 00:00:00 +00:00
   live contracts: <anonymous> (0utz) address[2]@new_admin
                   Admins (0utz) address[3]@admins
                   <anonymous> (0utz) address[1]@root

running TRANSFER[uid:3] address[1]@root -> address[3]@admins 0utz ("root", ("new_admin", address[2]@new_admin))
   timestamp: 1970-01-01 00:00:00 +00:00
=> live contracts: <anonymous> (0utz) address[2]@new_admin
                   Admins (0utz) address[3]@admins
                   <anonymous> (0utz) address[1]@root

running test script...
   timestamp: 1970-01-01 00:00:00 +00:00

Done running test `SetSource`

Notice how, in the last PRINT_STACK, the sender of the transfer is now root:

TRANSFER[uid:3] address[1]@root -> address[3]@admins ...