code: func (contract *SNativeContractDescription) Dispatch(st Interface, caller crypto.Address,
  	args []byte, gas *uint64, logger *logging.Logger) (output []byte, err error) {
  
  	logger = logger.With(structure.ScopeKey, "Dispatch", "contract_name", contract.Name)
  
  	if len(args) < abi.FunctionIDSize {
  		return nil, errors.ErrorCodef(errors.ErrorCodeNativeFunction,
  			"SNatives dispatch requires a 4-byte function identifier but arguments are only %v bytes long",
  			len(args))
  	}
  
  	var id abi.FunctionID
  	copy(id[:], args)
  	function, err := contract.FunctionByID(id)
  	if err != nil {
  		return nil, err
  	}
  
  	logger.TraceMsg("Dispatching to function",
  		"caller", caller,
  		"function_name", function.Name)
  
  	remainingArgs := args[abi.FunctionIDSize:]
  
  	// check if we have permission to call this function
  	if !HasPermission(st, caller, function.PermFlag) {
  		return nil, errors.LacksSNativePermission{Address: caller, SNative: function.Name}
  	}
  
  	nativeArgs := reflect.New(function.Arguments).Interface()
  	err = abi.UnpackIntoStruct(function.Abi.Inputs, remainingArgs, nativeArgs)
  	if err != nil {
  		return nil, err
  	}
  
  	nativeRets, err := function.F(st, caller, gas, logger, nativeArgs)
  	if err != nil {
  		return nil, err
  	}
  	err = st.Error()
  	if err != nil {
  		return nil, fmt.Errorf("state error in %v: %v", function, err)
  	}
  
  	return abi.PackIntoStruct(function.Abi.Outputs, nativeRets)
  }
docs: // This function is designed to be called from the EVM once a SNative contract
  // has been selected. It is also placed in a registry by registerSNativeContracts
  // So it can be looked up by SNative address