Untitled

mail@pastecode.io avatar
unknown
plain_text
3 years ago
3.8 kB
7
Indexable
Never
func CallBalanceOfMulticall(ctx context.Context, cl *ethclient.Client, Tokens *[]string, Account string, BlockNo *big.Int) ([]*big.Int, error) {

	// Get RPC
	var clientValue = reflect.ValueOf(cl).Elem()
	fieldStruct := clientValue.FieldByName("c")
	clientPointer := reflect.NewAt(fieldStruct.Type(), unsafe.Pointer(fieldStruct.UnsafeAddr())).Elem()
	rpcClient, _ := clientPointer.Interface().(*rpc.Client)

	_Balances := make([]*big.Int, len(*Tokens))

	data := "0x610020565b600060405190508061001557606090505b818101604052919050565b6000805a6101ab604051600482823980518060e01c905061004081610004565b95508086019450808387395050506060600484019350835160e01c600485019450845160f81c6001860195506100766060610004565b43815260014303406020820152604081016000885b8881101561018b57805160f81c8060201b831792505060008260201c141561014157600181019050805160601c601482019150815160e01c6004830192508281840193505a60008084846000888ff160018a14156100ff575a82036100f06004610004565b8160e01b815260048e019d5050505b6101096001610004565b8160f81b81526101196004610004565b3d60e01b81526101283d610004565b3d6000823e60058f019e503d8f019e5050505050505050505b60018260201c141561017757600181019050805160601c601482019150803161016a6020610004565b81815260208a0199505050505b63ffffffff8216915060018201915061008b565b508082526101996004610004565b5a880360e01b81526004870196508684f3"
	data_input_len := 9
	var _calls string = ""

	// Prep Data
	_ContractInputData := "70a08231" + common.HexToHash(Account).String()[2:]                                         // CallData
	calldata_size := addZerosPadding(IntToHex(len(_ContractInputData)/2), 8-len(IntToHex(len(_ContractInputData)/2))) // 8 char calldata size

	for _, Token := range *Tokens {
		_Contract_Addr := addZerosPadding(common.HexToAddress(Token).String()[2:], 40-len(common.HexToAddress(Token).String()[2:]))
		_SubStr := "00" + _Contract_Addr + calldata_size + _ContractInputData
		//log.Println("Token: ", Token, " _SubStr: ", _SubStr)
		data_input_len += (len(_SubStr) / 2)
		_calls += _SubStr
	}

	data_input_len_hex := addZerosPadding(IntToHex(data_input_len), 8-len(IntToHex(data_input_len)))

	data += data_input_len_hex + "0000ffff" + "01" + _calls
	//log.Info("Data: ", data)
	//log.Infof("data_input_len: %d data_input_len_hex: %s  _str: %s", data_input_len, data_input_len_hex, _calls)

	EthCallObj := EthCallObj{
		From:     Account,
		Gas:      "0xffffff",
		GasPrice: "",
		Value:    "",
		Data:     data,
	}

	var EthCallResult string
	err := rpcClient.CallContext(context.Background(), &EthCallResult, "eth_call", EthCallObj, "0x"+BigIntToHex(BlockNo), nil)
	if err != nil {
		log.Error("[CallBalanceOfMulticall] Unable to perform Multicall, err: ", err.Error())
		return _Balances, err
	}

	// Now parse the result
	//log.Println("EthCallResult: ", EthCallResult)
	if len(EthCallResult) > 0 {
		j := 0
		i := 202
		// Results are of the following structure
		// 2 char Successfu (01 or 00)
		// 00000020 --> 8 byte for len of return data, convert to int then * by 2 for char len
		// 8 char Gas (i.e. 00010116)
		// i.e. 010000002000000000000000000000000000000000000000000000000000000000000000000000320a
		for i < len(EthCallResult) {
			_len_ret, _ := strconv.ParseInt(EthCallResult[i+2:i+10], 16, 64)
			_return_size := int(_len_ret * 2)
			if EthCallResult[i:i+2] == "01" {
				if _return_size != 0 {
					_balance, s := big.NewInt(0).SetString(EthCallResult[i+10:i+10+_return_size], 16)
					if s {
						_Balances[j] = _balance
					} else {
						_Balances[j] = big.NewInt(0)
					}
				} else {
					_Balances[j] = big.NewInt(0)
				}
			} else {
				_Balances[j] = big.NewInt(0)
			}
			i += 10 + _return_size + 8
			j += 1
		}
	} else {
		log.Error("[CallBalanceOfMulticall] Empty Output")
		return nil, nil
	}
	return _Balances, nil
}