Submitted by nobody2018, also found by Stormy, 0xRobocop, and BARW
After LeverageMacroBase.doOperation is used to open a new CDP, there will be a POST CALL CHECK, which is used to check the new CDP. However, the current implementation incorrectly assumes that the index of the new CDP is the last one. In this case, there may be two impacts:
doOperation is used to open a new CDP, and there are roughly three steps: setup for POST CALL CHECK, openCdp, POST CALL CHECK for the created CDP.
L143, initialCdpIndex = sortedCdps.cdpCountOf(address(this)), which is used to count the number of CDPs already owned by this.
L145-168, Creats a CDP, the code here is not helpful in describing the issue and is therefore omitted.
L173, sortedCdps.cdpOfOwnerByIndex(address(this), initialCdpIndex) is used to get the id of the initialCdpIndex-th CDP owned by this. Thats the problem. Because initialCdpIndex is the number of CDPs owned before the new CDP was created (from L143), that is to say, the index of the created CDP is considered to be the last one.
Lets look at the code of cdpOfOwnerByIndex:
L144, _cdpOfOwnerByIndex(owner, index, dummyId, 0) is called.
L181, _currentCdpId = data.tail due to startNodeId = dummyId.
L189-194, If _currentIndex == index, the target cdpId is found and the loop exits. Otherwise, _currentIndex is increased by 1.
To better describe the problem, consider the following scenario:
this already has 1 CDP: A, and the entire linked list currently has 10 CDPs. Its topology is as follows:
New CDP is created via doOperation:
The root cause of this case is that the linked list is in descending order of NICR, and the NICR of the newly created CDP may be lower than the NICR of the already created CDP. In this case, the wrong cdpId will be returned.
In _openCdpCallback, borrowerOperations.openCdp returns the created cdpId, and we should specify a slot to store this value. Afterwards, read this slot directly in POST CALL CHECK and reset it to byte32(0). The slot can be obtained by using a method similar to keccak256("Badger.LeverageMacroBase.OpenCdpId").
Alex the Entreprenerd (Badger) confirmed and commented:
